C++ 主模板中类成员的定义和专门化期间的隐式实例化

C++ 主模板中类成员的定义和专门化期间的隐式实例化,c++,templates,c++11,enums,template-specialization,C++,Templates,C++11,Enums,Template Specialization,我有一个从§14.7.3/6[temp.expl.spec]分解的示例,该示例在主模板中定义了类成员枚举,并随后对其进行了专门化。以下内容不会以铿锵的方式编译: template<class T> struct A { enum E : T; }; template<class T> enum A<T>::E : T { eT }; template<> enum A<char>::E : char { echar }; /

我有一个从
§14.7.3/6[temp.expl.spec]
分解的示例,该示例在主模板中定义了类成员枚举,并随后对其进行了专门化。以下内容不会以铿锵的方式编译:

template<class T>
struct A {
    enum E : T;
};

template<class T>
enum A<T>::E : T { eT };

template<>
enum A<char>::E : char { echar }; // ill-formed, A<char>::E was instantiated
                                  // when A<char> was instantiated

// error: explicit specialization of 'E' after instantiation
模板
结构A{
枚举E:T;
};
模板
枚举A::E:T{eT};
模板
枚举A::E:char{echar};//格式错误,实例化了A::E
//当一个实例被实例化时
//错误:“E”在实例化后显式专门化
原因应该是非作用域成员枚举的定义是在专门化之前实例化的。14.7.1[温度仪表]/1:

类模板专门化的隐式实例化导致[…]非作用域成员枚举和成员匿名联合的定义的隐式实例化


我正试图弄明白为什么这是个问题。是因为如果枚举已经有定义,那么在专门化过程中会导致重新定义错误吗?

您需要专门化整个类定义:

template<class T>
struct A {
  enum E : T { eT };
};

template<>
struct A<char> {
  enum E : char { echar };
};
模板
结构A{
枚举E:T{eT};
};
模板
结构A{
枚举E:char{echar};
};

在您引用的示例前面的一段中,它说“如果一个模板、一个成员模板或一个类模板的一个成员被明确地专门化,那么在第一次使用该专门化之前,该专门化应在使用该专门化的每个翻译单元中声明,该专门化将导致隐式实例化;这为我编译,并提供了预期的专门化。(g++4.8.2)@T.C.我真的不知道这在这里会如何应用。@T.C.我已经读了好几遍了。它需要的声明是什么样子的?Clang++使用作用域枚举编译它。由于它们的定义似乎没有实例化,我认为这是兼容的,格式良好的。上面的规则要么来自C++03,其中forward decla环枚举是不可能的,或者这可能与名称查找有关(unscoped enum=>name被注入类作用域)。(关于匿名联合的部分向我建议它与名称查找有关。)[basic.lookup.qual]/1”类或命名空间成员或枚举数的名称可以在应用于表示其类、命名空间或枚举的嵌套名称说明符的
范围解析运算符之后引用。因此,一般规则是,对于
A::@
,可以将非作用域枚举成员作为名称
@
找到。通常,这意味着必须实例化枚举。在定义
enum
期间,您可能会为名称查找添加一个特殊规则。