类模板显式特化还可以声明其他内容吗?
如果此代码无效就好了。但它在概念上是合理的,GCC 接受它,尽管 Comeau 不这样做:(
template< typename > struct t;
template<> struct t< int > {} r; // Bad declarator! Don't pee on the carpet!
编辑:上面的代码可以编译,但是 r
似乎没有声明到任何范围,所以它本质上是忽略。)
显式专业化填充了模板和类之间的一种下部区域。显式特化声明的类型一旦定义就完整了。从编译器的角度来看,它不是模板。如果它是参数化模板,则声明对象是不可能的。考虑§14/3:
在模板声明、显式专门化或显式实例化中,声明中的 init-declarator-list 最多应包含一个声明符。当使用这样的声明来声明类模板时,不允许使用任何声明符。
“用于声明类模板”是什么意思?显然,主模板声明了类模板。根据 §14.5.5/1(FDIS 编号),部分专业化也是如此:
其中类模板名称为 simple-template-id 的模板声明是 simple-template-id 中命名的类模板的部分特化。
然而,当涉及到显式专业化时,标准以令牌序列 template<>
前面的声明来表述。它看起来像一个模板,并且它命名了一个模板名称,但它似乎没有声明一个模板。
真正奇怪的是,§14/3 将声明符的数量限制为“最多一个”。函数模板声明、显式特化或实例化必须只有一个声明符。任何涉及类模板的声明都必须恰好为零……除了显式专业化,这似乎被忽视了。老实说,GCC 拒绝允许
template<> struct t< int > {} r, s; // Offer valid one per specialization.
我倾向于同意 GCC 的解释,尽管它可能是无稽之谈。不幸的是,它可能抑制其检测丢失分号的能力。请让允许的声明符数量恰好为零!
It would be nice if this code were invalid. But it's conceptually sound, and GCC accepts it although Comeau doesn't:
template< typename > struct t;
template<> struct t< int > {} r; // Bad declarator! Don't pee on the carpet!
(Edit: the above compiles but r
seems no to be declared into any scope, so it is essentially ignored.)
Explicit specializations populate a kind of nether region between templates and classes. The type declared by an explicit specialization is complete once it is defined. From the compiler's standpoint, it is not a template. If it were a parameterized template, declaring an object would be impossible. Consider §14/3:
In a template-declaration, explicit specialization, or explicit instantiation the init-declarator-list in the dec- laration shall contain at most one declarator. When such a declaration is used to declare a class template, no declarator is permitted.
What does "is used to declare a class template" mean? Clearly a primary template declares a class template. And a partial specialization does too, according to §14.5.5/1 (FDIS numbers):
A template declaration in which the class template name is a simple-template-id is a partial specialization of the class template named in the simple-template-id.
When it comes to explicit specializations, though, the Standard speaks in terms of a declaration preceded by the token sequence template<>
. It looks like a template and it names a template-name, but it doesn't seem to declare a template.
The really bizarre thing is that §14/3 restricts the number of declarators to "at most one." A function template declaration, explicit specialization or instantiation must have exactly one declarator. Any declaration involving a class template must have exactly zero… except explicit specialization, which seems to fall through the cracks. Faithfully, GCC refuses to allow
template<> struct t< int > {} r, s; // Offer valid one per specialization.
I tend to agree with GCC's interpretation, nonsense as it may be. Unfortunately, it may be inhibiting its ability to detect missing semicolons. Please, let the number of allowed declarators be exactly zero!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
几点:第一,显式专业化不在下界
模板和类之间的区域;明确的专业化是
班级,时期。唯一的关系是与模板(除了
有趣的名字)是它将用来代替模板实例化
模板是否要在专业化类型上实例化。
其次,如果 §14/3 中的段落有问题,您认为
引用,它包括显式实例化;明确的
实例化是一个类定义,如果
合法,
那么也应该是合法的。 (我反对允许其中任何一个,但是那趟火车
已经出站了,由于 C 允许第一个,所以我们被困住了
)否则
,§14/3 中的陈述有点无关紧要。一个功能
模板必须恰好有一个声明符,并且恰好有一个类模板
零;没有必要试图将它们都包含在“最多一个”中
官样文章。 (如果我从头开始设计语言,我不会
允许在定义类或枚举的声明中使用任何声明符
类型。但同样,现在已经太晚了。)
而且我同意这很麻烦:(
至少 C++11 允许在函数定义后使用分号。)
Several points: first, explicit specializations are not in a nether
region between templates and classes; an explicit specialization is a
class, period. The only relation is has with templates (except for the
funny name) is that it will be used instead of a template instantiation
if the template is to be instantiated on the specialization type.
Secondly, if there is a problem with the paragraph in §14/3 that you
cite, it is that it includes explicit instantiation; an explicit
instantiation is a class definition, and if
is legal,
should be too. (I would argue against allowing either, but that train
has already left the station, and since C allows the first, we're stuck
with it.)
Otherwise, the statement in §14/3 is a bit irrelevant. A function
template must have exactly one declarator, and a class template exactly
zero; there's no need to try to englobe them both in some "at most one"
gobbledygook. (If I were designing the language from scratch, I'd not
allow any declarator in a declaration which defined a class or enum
type. But again, it's too late for that.)
And I agree that it's a bother:
(At least C++11 will allow a semicolon after the function definition.)
显式专业化和显式实例化不声明模板。他们声明一个template-id,它指的是一个专门化,它是一个类。
但是,这并不能验证我的示例。问题在于,在
template
或template<>
之后声明的所有内容分别是显式实例化或专门化的一部分。只有某些类型的实体可以被专门化或实例化,并且先前未声明的名称不是其中之一。考虑这些例子,这些例子无偿但合法地使用了详细类型说明符(§7.1.5.3):
据我所知,该标准对于指定哪个声明的名称是专门的名称是模糊的。该语言确实微弱地暗示每个此类声明仅适用于一个模板:§14.7.2/2
以及§14.7.3/2
解决此问题的唯一方法是,如果声明符还指定了合法的实例化/专业化,则忽略类型声明。
言归正传,问题中的示例在声明符中指定了非法特化,然后期望编译器回溯并特化该类型。鉴于 §14.7.2/1 和 §14.7.3/1 中允许执行的特化和声明的明确列表,抱怨
template<> 似乎更合理。结构体t<整数> {} r;
表示r
不是函数模板、成员函数模板、类模板的静态数据成员等。Explicit specialization and explicit instantiation do not declare a template. They declare a template-id which refers to a specialization, which is a class.
However, this doesn't validate my example. The problem is that everything declared following
template
ortemplate<>
is part of the explicit instantiation or specialization, respectively. Only certain types of entities may be specialized or instantiated, and previously-undeclared names aren't one of them.Consider these examples making gratuitous, but legal use of elaborated-type-specifiers (§7.1.5.3):
As far as I can tell, the Standard is fuzzy about specifying which declared name is the one specialized. The language does weakly imply that each such declaration applies to only one template: §14.7.2/2
and §14.7.3/2
The only way to resolve this is to ignore the type declaration if the declarator also specifies a legal instantiation/specialization.
Getting to the point, the examples in the question specify illegal specializations in the declarator and then expect the compiler to backtrack and specialize the type instead. Given the explicit lists of what specializations and declarations are allowed to do in §14.7.2/1 and §14.7.3/1, it seems more reasonable to complain about
template<> struct t< int > {} r;
thatr
is not a function template, member function template, static data member of a class template, etc.