ISO/IEC14882:2003之条款14.2——模板特化的名字
14.2 模板特化的名字
1、一个模板特化(14.7)可以被一个template_id所引用:
template-id:
template-name < template-argument-listopt >
template-name:
identifier
template-argument-list:
template-argument
template-argument-list , template-argument
template-argument:
assignment-expression
type-id
id-expression
[注:名字查找规则(3.4)用于将一个名字的使用与一个模板声明关联起来;即,将一个名字标识为一个template-name。]
2、对于被模板实参显式限定的一个template-name,该名字必须被获悉引用了一个模板。
3、在名字查找(3.4)发现一个名字是template-name之后,如果这个名字后面跟着一个<,那么这个<总是被采取为一个template-argument-list的开始,而不会被采纳为一个小于操作符。当解析一个template_id时,第一个非嵌套的>[注:围住一个dynamic_cast、static_cast、reinterpret_cast或const_cast的type-id的一个>,或是围住一个后续template_id的一个template-argument的一个>,被认为是用于此描述的目的而嵌套的]被采纳为template-argument-list的结束,而不是一个大于操作符。[例:
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)> >
——例结束][译者注:
template <typename T>
struct A
{
};
template <int N>
struct B
{
};
extern "C" void cpp_test(void)
{
A<B<100>> a; // error: 相当于A< B< (100 >> a);
A< B<100> > a; // OK: 其中,第一个>是嵌套的
}
]
4、当一个成员模板特化的名字出现在一个后缀表达式中的.或->之后,或是在一个qualified-id中的nested-name-specifier之后,并且后缀表达式或qualified-id显式地依赖于一个模板形参(14.6.2)时,成员模板名前必须添加关键字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>(); // 不良形式的: <意思是小于
T::template adjust<100>(); // OK: <作为模板实参列表的开始
}
——例结束]
5、如果加了关键字template前缀的一个名字不是一个成员模板的名字,那么程序是不良形式的。[注:关键字template不可以被提供给类模板的非模板成员。]此外,成员模板的名字不应该加关键字template最为前缀,如果postfix-expression或qualified-id没有出现在一个模板的作用域中。[注:就如同是在带有typename前缀的情况下,template前缀在其并非严格必要的情况下是被允许的;即,当->或.的左边的表达式,或nested-name-specifier并不依赖于一个template-parameter时]
[译者注:
template <typename T>
struct A
{
void f(void) const
{
}
template <typename Q>
struct I { };
};
template <typename T>
struct B
{
void f(const T& t)
{
t.f(); // OK
t.template f(); // 不良形式的
typename T::template I<int>(); // OK
}
};
extern "C" void cpp_test(void)
{
A<int> a;
B< A<int> >().f(a);
A<int>::I<char>(); // OK
A<int>:: template I<char>(); // 不良形式的,在模板的作用域外
}
]
6、命名一个类模板特化的一个template-id是一个class-name(条款9)。