以下源代码来自: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 回答
Clang和GCC是错误的,MSVC和EDG拒绝部分专业化定义是正确的 .
部分特化本身就是一个模板,而类模板定义是根据类定义在语法上构造的(在语法术语中,是类说明符) . 在这样的定义中,
Derived::Inner<int, _>
是类头名,Derived::
是嵌套名称说明符 .标准中的[9p11]说:
所以,你必须使用
Base::Inner<int, _>
.正如评论中所指出的,上面的引用也适用于类模板显式特化定义(它们的语法生成也最终使用class-head-name) .
以下内容并不直接适用于您的示例,但我发现值得一提 .
请注意,上面的引用引用了类模板(或显式特化)定义,而不是诸如的声明
从语法上讲,
struct Derived::Inner<int, _>
中有一个精心设计的类型说明符,上面的段落不适用于此 . 因此,标准措辞在技术上允许这样的声明 .这似乎不是一种疏忽:上述措辞是由DR284的决议引入的,其中包括评论:
拟议的决议包括精心设计的指定人员,但这些措辞已从最后的措辞中删除 .
然而,MSVC和EDG都不接受这样的声明(坦率地说,如果他们这样做,我会发现它令人困惑) . DR中的注释似乎表明意图只允许那些不是声明的详细类型说明符,但看起来这并没有反映在措辞中(我认为标准错误) .