3

我正在用 clang 编译以下测试代码:

template<typename T> struct S1
{
   struct S2{
       enum class E1;
       enum class E2: T;
       enum class E3: short;
    };

    typename S2::E1 b1;
    typename S2::E2 b2;
    typename S2::E3 b3;

    enum class S1::S2::E1 {e11,e12};
    enum class S1::S2::E2 : T {e21,e22};
    enum class S1::S2::E3 : short {e31,e32};
};

template struct S1<int>;

我收到错误:模板专业化或定义需要一个与嵌套类型“S1< T >”相对应的模板参数列表。我的猜测是因为在添加成员时定义了 struct S1

enum class S1::S2::E1 {e11,e12} 
enum class S1::S2::E2 : T {e21,e22};
enum class S1::S2::E3 : short {e31,e32};

编译器不知道 T 是什么,因为 S1 尚未实例化,因此 T 无法解析。因此,编译器不知道枚举成员的大小,因此会引发错误。它是否正确?标准中有规定吗?

注意:gcc 不会抛出任何此类错误。

4

1 回答 1

1

根本不允许定义enum这样的。n3337 中的第 7.2/4 段指出:

如果enum-key后跟nested-name-specifier,则enum-specifier应引用先前直接在嵌套名称说明符所指的类或命名空间中声明的枚举(即,既不继承也不引入通过using-declaration),并且枚举说明符应出现在包含先前声明的命名空间中。

当然,错误消息并不完全是一流的。您的示例可以大大简化为:

template<typename T> struct S1
{
   struct S2 {
       enum class E;
   };

   enum class S2::E {};
};

这将产生相同的错误消息。

有效的选项是:

// definition in the scope that the declaration appears in
template<typename T> struct S1
{
   struct S2 {
       enum class E;
       enum class E {};
   };
};

或者

// definition in the enclosing namespace scope
template<typename T> struct S1
{
   struct S2 {
       enum class E;
   };
};

template<typename T>
enum class S1<T>::S2::E {};

同样的规则也适用于嵌套类(见 9.7/3)。如果你试试这个

template<typename T>
struct S1
{
   struct S2 {
       struct S3;
   };

   struct S2::S3 {};
};

那么 GCC 也会产生一个(同样无益的)错误。它对枚举不做同样的事情似乎是一个错误。

你自己对错误的解释是不正确的。在模板的定义中,编译器不需要(显然也不能)知道是什么T。只有在实例化模板时才需要它。还有其他类似的template<typename T> struct X { T obj; };工作吗?

于 2013-09-26T13:03:02.183 回答