如果此代码无效,那就太好了。但它在概念上是合理的,而GCC accepts it虽然却没有:
template< typename > struct t;
template<> struct t< int > {} r; // Bad declarator! Don't pee on the carpet!
(编辑:以上编译但r
似乎没有被声明为into any scope,因此它基本上被忽略了。)
显式特化在模板和类之间填充一种下层区域。一旦定义,显式特化声明的类型就完成了。从编译器的角度来看,它不是模板。如果它是参数化模板,则无法声明对象。考虑§14/ 3:
在模板声明,显式特化或显式实例化中,声明中的init-declarator-list最多应包含一个声明符。当这样的声明用于声明类模板时,不允许声明者。
“用于声明类模板”是什么意思?显然,主模板声明了一个类模板。根据§14.5.5/ 1(FDIS编号),部分专业化也是如此:
模板声明,其中类模板名称是simple-template-id,是simple-template-id中命名的类模板的部分特化。
但是,当涉及到显式特化时,标准就会以令牌序列template<>
之前的声明来表达。它看起来像模板,它命名一个模板名称,但它似乎没有声明模板。
真正奇怪的是,§14/ 3将声明者的数量限制为“最多一个”。函数模板声明,显式特化或实例化必须只有一个声明符。涉及类模板的任何声明必须正好为零...除了显式特化,这似乎是通过裂缝。忠实地,GCC refuses to allow
template<> struct t< int > {} r, s; // Offer valid one per specialization.
我倾向于同意海湾合作委员会的解释,尽管可能是胡说八道。不幸的是,它可能inhibiting能够检测丢失的分号。请允许声明者的数量正好为零!
答案 0 :(得分:13)
有几点:首先,明确的专业化并不是一件好事 模板和类之间的区域;明确的专业化是一个 上课,期间。唯一的关系是模板(除了 有趣的名称)是它将被用来代替模板实例化 如果要在专业化类型上实例化模板。
其次,如果§14/ 3中的段落存在问题 引用,它包括明确的实例化;明确的 instantiation是一个类定义,如果是
struct S {} s, *p;
是合法的,
template<> struct T<int> {} s, *p;
也应该。 (我会反对允许,但那列车 已经离开了车站,而且由于C允许第一次,我们被卡住了 用它。)
否则,§14/ 3中的陈述有点无关紧要。一个功能 模板必须只有一个声明符和一个类模板 零;没有必要尝试将它们两者都用在“最多一个”中 官样文章。 (如果我从头开始设计语言,我不会 允许在声明中定义类或枚举的任何声明者 类型。但同样,这已经太迟了。)
我同意这是一个麻烦:
template<> struct T<int> {}; // Requires a ';'
template<> void f<int>() {} // ';' forbidden
(在函数定义之后,至少C ++ 11将允许使用分号。)
答案 1 :(得分:1)
显式特化和显式实例化不会声明模板。他们声明了一个 template-id ,它指的是一个专门化,这是一个类。
但是,这不会验证我的示例。问题是在template
或template<>
之后声明的所有分别是显式实例化或特化的一部分。只有某些类型的实体可以是专门的或实例化的,而以前未声明的名称不是其中之一。
考虑这些例子,使用详细类型说明符(第7.1.5.3节)进行无偿但合法的使用:
template< typename T > struct s;
template< typename T > s< int > *f() {}
template<> struct u *f< char >(); // struct u is declared
u *p = 0; // see, we can use its name now.
template<> struct s< int > *f< int >(); // s<int> declared but not specialized
template struct s< int > *f< long >(); // s<int> declared but not instantiated
据我所知,标准对于指定哪个声明的名称是专门的名称是模糊的。该语言的确暗示每个此类声明仅适用于一个模板:§14.7.2/ 2
如果显式实例化适用于类,函数或成员模板专门化......
和§14.7.3/ 2
应在模板所属的名称空间中声明显式特化...
解决此问题的唯一方法是,如果声明符还指定了合法的实例化/特化,则忽略类型声明。
说到这一点,问题中的示例在声明符中指定非法特化,然后期望编译器回溯并专门化类型。鉴于§14.7.2/ 1和§14.7.3/ 1中允许执行哪些特化和声明的明确列表,抱怨template<> struct t< int > {} r;
r
不是函数似乎更合理模板,成员函数模板,类模板的静态数据成员等