【问题标题】:Specialization of inherited nested template class继承嵌套模板类的特化
【发布时间】:2016-07-06 02:58:53
【问题描述】:

以下源代码来自: 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 {};

我有一个关于专门继承类的问题,所以我搜索了一下,找到了上面的问题。上述问题中的源代码在 gcc/clang 中编译时没有任何问题,但 msvc 拒绝编译它,发出 C2427(请参阅https://msdn.microsoft.com/en-us/library/10het5hx.aspx)。

我认为上面的情况(特化非模板类的嵌套模板类)与https://msdn.microsoft.com/en-us/library/10het5hx.aspx中描述的情况(定义模板类的嵌套非模板类)有很大不同。

msvc 与 gcc/clang 哪一个是错误的?还是只是标准不清楚来指定这种行为?

我希望 msvc 是错的...

【问题讨论】:

    标签: c++ inheritance language-lawyer inner-classes template-specialization


    【解决方案1】:

    Clang 和 GCC 是错误的,MSVC 和 EDG 拒绝该部分专业化定义是正确的。

    部分特化本身就是一个模板,并且类模板定义是根据类定义在语法上构造的(在语法术语中,类说明符)。在这样的定义中,Derived::Inner&lt;int, _&gt;class-head-nameDerived::nested-name-specifier

    [9p11] 在标准中说:

    如果 class-head-name 包含 nested-name-specifier,则 class-specifier 应该引用之前声明的类 直接在 nested-name-specifier 所在的类或命名空间中 引用,或在其内联命名空间集(7.3.1)的元素中 命名空间(即,不仅仅是由一个 using-declaration),并且 class-specifier 应出现在 包含先前声明的命名空间。 [...]

    所以,你必须使用Base::Inner&lt;int, _&gt;


    如 cmets 中所述,上面的引用也适用于类模板显式特化定义(它们的语法产生也最终使用 class-head-name)。


    以下内容并不直接适用于您的示例,但我觉得值得一提。

    请注意,上面的引用是指类模板(或显式特化)定义,而不是诸如

    之类的声明
    template<class _> struct Derived::Inner<int, _>;
    

    在语法上,struct Derived::Inner&lt;int, _&gt; 中有一个详细类型说明符,上面的段落不适用。因此,标准措辞在技术上允许此类声明。

    这似乎不是疏忽:上面的措辞是由DR284 的决议引入的,其中包括评论:

    人们认为这应该是类定义所必需的, 但不是一般的详细类型说明符(它们是 引用,而不是声明)。 [...]

    提议的决议包括详细类型说明符,但这些已从最终措辞中删除。

    但是,MSVC 和 EDG 都不接受此类声明(坦率地说,如果他们接受了,我会觉得很困惑)。 DR 中的评论似乎表明其意图是只允许不是声明的详细类型说明符,但看起来这并没有反映在措辞中(一个标准错误,我认为)。

    【讨论】:

    • 太糟糕了...如果我可以使用派生类名专门化嵌套类模板,那就太好了...无论如何,感谢您提供的非常丰富的答案!顺便说一句,[9p11] 是否也适用于显式专业化?当我删除示例中的 dummy 参数时,msvc 似乎仍然拒绝。
    • @JunekeyJeon 是的,据我所知。
    猜你喜欢
    • 2013-06-12
    • 1970-01-01
    • 2019-01-04
    • 2016-01-11
    • 1970-01-01
    • 2017-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多