C+中的一些混淆+;模板 我现在正在读这本书,C++模板:完整指南。在一个段落中,我被卡住了,无法理解术语,以下是段落:

C+中的一些混淆+;模板 我现在正在读这本书,C++模板:完整指南。在一个段落中,我被卡住了,无法理解术语,以下是段落:,c++,templates,C++,Templates,一个基本原则是,任何模板参数都必须是 可在编译时确定的数量或值。当成为 稍后明确,这一要求将转化为对客户的巨大好处 模板实体的运行时成本因为模板参数 最终被编译时值替换,它们可以自己 用于形成编译时表达式。这一点在过去被利用了 ArrayClass模板以调整成员数组的大小。一个房间大小 数组必须是所谓的常量表达式,并且模板 参数N符合此条件。 我们可以把这个推理推得更远一点:因为模板 参数是编译时实体,也可用于创建 有效的模板参数。下面是一个例子: 模板 类{ 公众: 课堂内容; }; 请注意

一个基本原则是,任何模板参数都必须是 可在编译时确定的数量或值。当成为 稍后明确,这一要求将转化为对客户的巨大好处 模板实体的运行时成本因为模板参数 最终被编译时值替换,它们可以自己 用于形成编译时表达式。这一点在过去被利用了 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);
}