它必须是一个整数常量表达式。 5.19 的标准文档对此进行了解释:
整型常量表达式只能包含字面量 (2.13)、枚举器、常量变量或使用常量表达式初始化的整型或枚举类型的静态数据成员 (8.5)、整型或枚举类型的非类型模板参数,以及 sizeof表达式。浮动文字 (2.13.3) 只有在转换为整数或枚举类型时才能出现。只能使用到整数或枚举类型的类型转换。
请注意,“integral”是“integer”的另一个术语,但与“int”不同。例如,“char”具有整数/整数类型,但显然不是 int 类型。所以具体来说,以下是允许的
10 or 10L or anything like that
enum { THIS, OR, THAT };
int const this_one = 10;
-
sizeof(char)
- 当然,上面详述的任何其他模板参数
其中任何一个都可以用作具有相应类型的整数类型的参数的模板参数。但是仍然应用了一些转换。因此,如果它想要一个 int 并且您传递一个 char,它会自动将 char 提升为 int。如果您提供一个枚举器并且它需要一个 int,则相同。
所以根据这些规则,如果你有
extern const int SomeName;
并且它没有看到使用整数常量表达式初始化该常量的定义,它不能用作模板参数。但它当然可以用作函数参数。这些不需要在编译时知道,因为它们不是类型的一部分。当您命名模板特化时,您使用的参数就成为类型的一部分:
MyGreatStack<int, 4> // 4 is now part of the type MyGreatStack<int, 4>!
请注意,还有其他方法可以将SomeName 作为参数传递。但是,整数模板参数可以不接受所有这些。您可以通过引用参数接受上述内容,例如
template<const int& V> struct NowItWorks { };
它会接受上面的SomeName。现在,不是一个值,而是一个在整个程序中唯一的特定位置(因为变量具有extern 链接)已被选择。