首页 文章

继承嵌套模板类的专业化

提问于
浏览
6

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

我有一个关于专门继承类的问题,所以我用Google搜索,并找出上面的问题 . 上面问题中的源代码没有编译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错了......

1 回答

  • 2

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

    部分特化本身就是一个模板,而类模板定义是根据类定义在语法上构造的(在语法术语中,是类说明符) . 在这样的定义中, Derived::Inner<int, _> 是类头名, Derived:: 是嵌套名称说明符 .

    标准中的[9p11]说:

    如果class-head-name包含嵌套名称说明符,则类说明符应引用先前在嵌套名称说明符所引用的类或命名空间中直接声明的类,或者在该命名空间的内联命名空间集(7.3.1)(即,不仅仅是由using-declaration继承或引入),并且类说明符应出现在包含前一个声明的命名空间中 . [...]

    所以,你必须使用 Base::Inner<int, _> .


    正如评论中所指出的,上面的引用也适用于类模板显式特化定义(它们的语法生成也最终使用class-head-name) .


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

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

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

    从语法上讲, struct Derived::Inner<int, _> 中有一个精心设计的类型说明符,上面的段落不适用于此 . 因此,标准措辞在技术上允许这样的声明 .

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

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

    拟议的决议包括精心设计的指定人员,但这些措辞已从最后的措辞中删除 .

    然而,MSVC和EDG都不接受这样的声明(坦率地说,如果他们这样做,我会发现它令人困惑) . DR中的注释似乎表明意图只允许那些不是声明的详细类型说明符,但看起来这并没有反映在措辞中(我认为标准错误) .

相关问题