模板非类型参数的限制规则如下:
非类型、非模板模板参数的模板参数应为以下之一:
——对于整型或枚举类型的非类型模板参数,模板参数类型的转换常量表达式(5.19);或者
— 非类型模板参数的名称;或者
— 常量表达式(5.19),指定具有静态存储持续时间和外部或内部链接的对象或具有外部或内部链接的函数的地址,包括函数模板和函数模板 ID,但不包括非静态类成员,表示为(忽略括号)作为
& id-表达式,但如果名称引用函数或数组,则可以省略 &;如果相应的模板参数是引用,则应省略 &;或者
— 计算结果为空指针值的常量表达式 (4.10);或者
— 计算结果为空成员指针值的常量表达式 (4.11);或者
— 指向成员的指针,如 5.3.1 中所述表示。
2 [ 注意:字符串文字 (2.14.5) 不满足任何这些类别的要求,因此不是可接受的模板参数。
[ Example:
template<class T, const char* p> class X {
/ ... /
};
X<int, "Studebaker"> x1; // error: string literal as template-argument
const char p[] = "Vivisectionist";
X<int,p> x2; // OK
—end example ] —end note ]
那么为什么字符串文字不能用作非类型参数的参数呢?
const char arr[5] = "1234";
arr 具有相同类型常量字符[5] as
"1234";
arr 具有外部链接,这就是为什么在 c++11 标准之前允许使用 arr 作为非类型模板参数。
但现在指向具有内部链接(静态存储)的对象的指针也允许用作非类型模板参数,并且字符串文字具有内部链接。