2013-09-26 8 views
3

Я составителя следующий тестовый код с лязгом:Динамическая инициализация класса перечислений внутри шаблона структуры

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> ». Я думаю, так как структура 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 не выбрасывает такую ​​ошибку.

ответ

1

Это просто не разрешено определять enum. Пункт 7.2/4 в n3337 состояниях:

Если перечисления ключа сопровождается имени вложенного-Специфический эр, в перечисления-Специфическое эр должен относиться к перечислению, что ранее объявленным непосредственно в классе или пространстве имен, к которому имени вложенного-специфический эр относится (т.е. ни по наследству, ни введенный в с использованием-декларацией) и перечисления-специфический эр должен появляться в пространстве имен , содержащий предыдущую декларацию.

Предоставлено сообщение об ошибке не совсем звездное. Ваш пример может быть значительно упрощен:

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; }; работы?

+0

Спасибо. Я понял! – sarda

Смежные вопросы