14.2 模板特化的名字
1. 模板特化可以通过模板 id 来表示:
模板 id :
模板名字 < 模板实参列表 opt >
模板名字:
标识符
模板实参列表:
模板实参
模板实参列表 , 模板实参
模板实参:
赋值表达式
类型 id
id 表达式
【注:名字查找规则用来将名字的使用和模板声明联系起来,也就是说,将一个名字标识为模板名字。】
2. 对于被模板实参显式限定的模板名字来说,为了表示一个模板,该名字必须已经可见。
3. 名字查找发现一个名字是个模板名后,如果该名字之后是 < 符号,该 < 符号总被认为是模板实参列表的开始,永远不会被当做小于号。当解析模板 id 的时候,第一个非嵌套的 > 符号被当做模板实参列表的结束,而不是大于号。【例:
template<int i> class X { /* ... */ };
X< 1>2 > x1; // 语法错误
X<(1>2)> x2; // OK
template<class T> class Y { /* ... */ };
Y< X<1> > x3; // OK
Y<X<6>> 1> > x4; // OK: Y< X< (6>>1) > >
】
4. 当成员模板特化的名字出现在后缀表达式的 . 或 -> 操作符之后,或出现在限定的 id 中的嵌套名字说明符中,并且后缀表达式或限定的 id 显式地依赖于一个模板参数,成员模板名字前必须加上前缀 template 。否则,该名字被认为用来命名一个非模板。【例:
class X {
public:
template<size_t> X* alloc();
template<size_t> static X* adjust();
};
template<class T> void f(T* p)
{
T* p1 = p->alloc<200>();
// 非法 : < 表示小于号
T* p2 = p->template alloc<200>();
// OK: < 之后是模板实参列表
T::adjust<100>();
// ill-formed: < 表示小于号
T::template adjust<100>();
// OK : < 之后是模板实参列表
}
】
5. 如果名字的前缀是 template ,但是该名字不是成员模板的名字,程序就是非法的。【注:关键字 template 不能用于类模板的非模板成员。】更进一层,如果后缀表达式或限定的 id 不是出现在模板作用域中,成员模板的名字前不能加 template 。【注:正如 typename 前缀的情况一样, template 前缀在不是绝对必需的情况下也是允许使用的;即当表达式在 . 或 -> 左边,或嵌套的名字说明符不依赖模板参数的时候。】
6. 命名类模板特化的模板 id 是个类名。