有一个类似的问题here,但它与使用typename
关键字的模板相关。
给出一个模板:
template < int X, char Y >
struct foo
{
char myArray[ X <= 0 ? 1 : X ];
static const char Z = Y;
}
是否会在foo
的所有实例之间共享该静态成员,或者编译器是否会看到该模板已使用不同的参数调用并创建新类型?
答案 0 :(得分:3)
在那里分配的静态常量成员会根据模板参数传递的值而更改。缩短它是这样的:
template<int X>
struct foo {
static const int value = X;
};
您不希望foo<10>::value
等于foo<11>::value
吗?这通常用于模板元编程,因为该静态常量的值取决于模板参数。
答案 1 :(得分:3)
实际上,您定义的模板参数是非类型参数,而不是其他两种模板参数:type-parameters和template-parameters。
但是,它们仍然是模板参数,您将获得每个不同模板参数集的全新数据类型。例如,foo<3,'a'>
是与foo<4,'a'>
不同的数据类型,与foo<3,'b'>
不同,等等。
因此,静态成员也会为每个模板参数选择单独分配和初始化。
在这方面,非类型参数,类型参数和模板参数都以相同的方式工作。
供参考,来自标准(C ++ 11):
(§14.7/ 6)从模板实例化的每个类模板特化都有自己的任何静态成员的副本。 [例如:
template<class T> class X { static T s; }; template<class T> T X<T>::s = 0; X<int> aa; X<char*> bb;
X<int>
有一个s
类型的静态成员int
,而X<char*>
有s
类型的静态成员char*
。 - 结束例子]
上述标准给出的示例涉及类型参数,但第14.7 / 6节是模板的一般讨论的一部分。更广泛的上下文清楚地表明,这适用于使用非类型参数的模板(或类型,非类型和模板参数的组合)。
还有一个关于模板实例化的类型等价的部分,它解释了在什么情况下使用非类型参数的模板实例被认为是相等的(我强调的相关部分):
(§14/ 1)如果是,则两个模板ID指的是相同的类或函数 - 他们的模板名称,operator-function-id或literal-operator-id引用相同的模板和
- 它们对应的类型模板参数是相同的类型和
- 它们对应的整数或枚举类型的非类型模板参数具有相同的值和
- 它们对应的指针类型的非类型模板参数引用相同的外部对象或函数,或者都是空指针值和
- 它们对应的指向成员类型的非类型模板参数引用相同的类成员或者都是空成员指针值和
- 它们对应的非类型模板 - 引用类型参数引用相同的外部对象或函数和
- 相应的模板模板参数引用相同的模板。
放入上下文,这意味着同一类模板的两个实例化构成了两种不同的数据类型,即使它们只有一个非类型参数的值不同。