简体   繁体   English

继承的嵌套模板类的专业化

[英]Specialization of inherited nested template class

The following source code is brought from: Understanding partial specialization of inherited nested class templates 来自以下源代码: 了解继承的嵌套类模板的部分专业化

#include <type_traits>
struct Base
{
    template<class U, class _ = void> struct Inner: std::true_type {};
    template<class _> struct Inner<char, _>: std::false_type {};
};
struct Derived : Base
{
};

template<class _> struct Derived::Inner<int, _>: std::false_type {};

I had an issue about specializing inherited class, so I googled, and find out the question above. 我有一个关于专门继承类的问题,所以我用Google搜索了一下,找出了上面的问题。 The source code in the question above compiled w/o any problem in gcc/clang, but msvc refuses to compile it, issuing C2427 (see https://msdn.microsoft.com/en-us/library/10het5hx.aspx ). 上面问题中的源代码编译了gcc / clang中的任何问题,但msvc拒绝编译它,发出C2427(请参阅https://msdn.microsoft.com/zh-cn/library/10het5hx.aspx )。

Situation of the above (specialize the nested template class of a non-template class) is quite different from the situation described in https://msdn.microsoft.com/en-us/library/10het5hx.aspx (define the nested non-template class of a template class), I think. 以上情况(专门用于非模板类的嵌套模板类)与https://msdn.microsoft.com/zh-cn/library/10het5hx.aspx中描述的情况有很大不同(定义嵌套的非模板类,我认为是模板类)。

Which one of msvc vs. gcc/clang is wrong? msvc与gcc / clang中的哪一个是错误的? Or just the standard is so unclear to specify this behavior? 还是只是标准尚不清楚以指定这种行为?

I hope msvc is wrong... 我希望msvc是错误的...

Clang and GCC are wrong, and MSVC and EDG are right to reject that partial specialization definition. Clang和GCC是错误的,MSVC和EDG拒绝该部分专业化定义是正确的。

A partial specialization is itself a template, and a class template definition is syntactically constructed in terms of a class definition (in grammar terms, a class-specifier ). 部分专业化本身就是模板,而类模板定义是根据类定义(在语法上为class-specifier )语法构建的。 Within such a definition, Derived::Inner<int, _> is a class-head-name , with Derived:: being a nested-name-specifier . 在这样的定义中, Derived::Inner<int, _>是一个类头名称 ,而Derived::是一个嵌套名称说明符

[9p11] in the Standard says: 标准中的[9p11]说:

If a class-head-name contains a nested-name-specifier , the class-specifier shall refer to a class that was previously declared directly in the class or namespace to which the nested-name-specifier refers, or in an element of the inline namespace set (7.3.1) of that namespace (ie, not merely inherited or introduced by a using-declaration ), and the class-specifier shall appear in a namespace enclosing the previous declaration. 如果一个类名包含一个嵌套名称说明符 ,则该类说明符应引用先前在该嵌套名称说明符所引用的类或名称空间中或在其元素中直接声明的类。该名称空间的内联名称空间集(7.3.1)(即,不仅由using-declaration继承或引入),并且class-specifier应出现在包含先前声明的名称空间中。 [...] [...]

So, you have to use Base::Inner<int, _> . 因此,您必须使用Base::Inner<int, _>


As noted in the comments, the quote above applies to class template explicit specialization definitions as well (their grammar production also ends up using class-head-name ). 如评论中所述,以上引用也适用于类模板显式专业化定义(它们的语法生成也最终使用class-head-name结束 )。


The following doesn't apply directly to your example, but I found it worth mentioning. 以下内容不适用于您的示例,但我发现值得一提。

Note that the quote above refers to class template (or explicit specialization) definitions, not declarations such as 请注意,上面的引用引用的是类模板(或显式专业化)定义,而不是诸如

template<class _> struct Derived::Inner<int, _>;

Syntactically, struct Derived::Inner<int, _> in there is an elaborated-type-specifier , to which the paragraph above doesn't apply. 从语法上讲, struct Derived::Inner<int, _>中有一个详尽的类型说明符 ,以上段落不适用于该说明符 So, the Standard wording technically allows such declarations. 因此,标准措词在技术上允许此类声明。

This doesn't seem to be an oversight: the wording above was introduced by the resolution of DR284 , which includes the comment: 这似乎不是疏忽:上面的措辞是由DR284决议引入的,其中包括评论:

The sentiment was that this should be required on class definitions, but not on elaborated type specifiers in general (which are references, not declarations). 人们的观点是,这应该在类定义上是必需的,但一般而言在详细的类型说明符(不是引用,而是声明)上都不需要。 [...] [...]

The proposed resolution included elaborated-type-specifiers , but those were removed from the final wording. 拟议的决议包括详细的类型说明符 ,但这些内容已从最终措辞中删除。

However, neither MSVC nor EDG accept such declarations (and frankly I'd find it confusing if they did). 但是,MSVC和EDG都不接受此类声明(坦率地说,如果这样做,我会感到困惑)。 The comment in the DR seems to indicate that the intent was to allow only elaborated-type-specifiers that are not also declarations, but it looks like this wasn't reflected in the wording (a Standard bug, I think). DR中的注释似乎表明,其目的是仅允许既不是声明也不是声明的详尽的类型说明符 ,但这似乎没有体现在措辞上(我认为是标准错误)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM