C+中的一些混淆+;模板 我现在正在读这本书,C++模板:完整指南。在一个段落中,我被卡住了,无法理解术语,以下是段落:
一个基本原则是,任何模板参数都必须是 可在编译时确定的数量或值。当成为 稍后明确,这一要求将转化为对客户的巨大好处 模板实体的运行时成本因为模板参数 最终被编译时值替换,它们可以自己 用于形成编译时表达式。这一点在过去被利用了 ArrayClass模板以调整成员数组的大小。一个房间大小 数组必须是所谓的常量表达式,并且模板 参数N符合此条件。 我们可以把这个推理推得更远一点:因为模板 参数是编译时实体,也可用于创建 有效的模板参数。下面是一个例子:C+中的一些混淆+;模板 我现在正在读这本书,C++模板:完整指南。在一个段落中,我被卡住了,无法理解术语,以下是段落:,c++,templates,C++,Templates,一个基本原则是,任何模板参数都必须是 可在编译时确定的数量或值。当成为 稍后明确,这一要求将转化为对客户的巨大好处 模板实体的运行时成本因为模板参数 最终被编译时值替换,它们可以自己 用于形成编译时表达式。这一点在过去被利用了 ArrayClass模板以调整成员数组的大小。一个房间大小 数组必须是所谓的常量表达式,并且模板 参数N符合此条件。 我们可以把这个推理推得更远一点:因为模板 参数是编译时实体,也可用于创建 有效的模板参数。下面是一个例子: 模板 类{ 公众: 课堂内容; }; 请注意
模板
类{
公众:
课堂内容;
};
请注意,在本例中,名称T既是一个模板参数,也是一个
模板参数。因此,可以使用一种机制来启用
从简单模板构造更复杂的模板。当然
这与允许我们这样做的机制没有根本区别
组装类型和函数
我什么都不懂。我非常感谢任何简单易懂的词语的帮助
编辑:
Arrayinclass:
template <typename T, int N>
class ArrayInClass {
public:
T array[N];
};
模板
类数组类{
公众:
T数组[N];
};
意思是在类模板中,teat
,模板参数T
也被用作成员变量的参数,ArrayInClass
因此,如果您将teat
实例化为,例如:
Dozen<float> my_dozen;
打我的一打;
然后编译器将生成如下代码:
class Dozen<float> {
public:
ArrayInClass<float,12> contents;
};
类{
公众:
课堂内容;
};
您以粗体突出显示的部分表示,当您定义类Foo
时,编译器必须在编译时知道T
;i、 e.它不能是不完整的类型
对于实例化Foo
的每个不同类型T
,编译器将创建一个全新的类型(Foo
,Foo
等),该类型与实例化Foo的任何其他类型无关,尽管它们可能都具有Foo
实现定义的相同行为
在您发布的示例中,我假设ArrayInClass
创建了一个T
类型的数组,其中包含N
元素
比如说,
template< typename T, size_t N >
class ArrayInClass
{
T myArr_[N];
public:
// public interface
};
模板
类数组类
{
T myArr_[N];
公众:
//公共接口
};
类中的数组不是由动态分配的,而是声明为静态数组,尽管它使用
N
作为数组长度。这是可能的,因为编译器将在实例化ArrayClass
时替换指定为模板参数的长度。如果编译器无法在编译时确定N
,这是不可能的。当作者说模板参数最终被编译时常量替换时,他的意思就是这样。例如,在以下众所周知的示例中,生成的代码是一个数值常量(即乘法发生在编译时,而不是运行时):
#include <iostream>
template <int N>
struct Factorial
{
enum { value = N * Factorial<N-1>::value };
};
template <>
struct Factorial<1>
{
enum { value = 1 };
};
// example use
int main()
{
std::cout << Factorial<5>::value << endl;
return 0;
}
#包括
模板
结构阶乘
{
枚举{value=N*阶乘::值};
};
模板
结构阶乘
{
枚举{值=1};
};
//示例使用
int main()
{
STD::CUT C++中有一定的表达式,需要在编译时知道。例如:
int someArray[30];
< > >代码> 30 <代码>必须是C++中的编译时常数,它可能是:
int someArray[30 + 3];
这很好,因为编译器拥有在编译时计算数组大小所需的所有信息。但是:
void MyFunc(int numItems) {
int someArray[30 + numItems];
}
这不是编译时常量,因为用户可以使用任何整数值调用MyFunc
。编译器不知道数组的大小,因此这是一个编译器错误
(注:C99允许创建任意大小的数组,如C++。)
由于模板参数是编译时值,因此可以将其传递到需要编译时值的其他位置:
template<int ArrayLen> void MyFunc() {
int someArray[30 + ArrayLen];
}
这个新模板函数调用的旧模板的数组比给定的数组大3。好的,根据您的评论,这里有一点推理:
假设您有一个模板:
template <typename T> struct Moo { };
template <typename U>
class MyClass
{
int a;
U b;
Moo<U> m;
};
template <typename T>
class Dozen
{
...
};
这也很好,因为Moo
是一个有效的类型。同样,没问题。但现在让我们概括MyClass并将其作为模板:
template <typename T> struct Moo { };
template <typename U>
class MyClass
{
int a;
U b;
Moo<U> m;
};
template <typename T>
class Dozen
{
...
};
模板
类MyClass
{
INTA;
U b;
穆姆;
};
现在再说一遍,MyClass
,必须在编译时知道Zoo
。因此,依赖类型Moo
在MyClass
中被替换为Moo
,并且因为知道Zoo
,所以现在也知道了该成员类型
你引用的黑体字只是说这种推理是有效的,你得到了一些有效的东西
对于类型名来说,这并不十分令人兴奋,因为所有类型名在编译时都是已知的,但模板参数也可以是非类型名,即整数值。现在,这些参数也必须在编译时已知,并且可以以相同的方式传播它们。我认为,您很难找到更清晰的表达式来表达我想,它们很好地解释了这个问题
如果您仍然需要帮助来理解这个想法,请首先尝试理解三个关键词:模板、参数和参数
// T states parameter of Dozen template
template <typename T>
class Dozen
{
// the T is argument used to instantiate concrete type from another template
ArrayInClass<T,12> contents;
};
void foo(int a)
{
bar(a);
}