2011-02-10 3 views
4

Это то, что я хочу сделать:перечисления в качестве шаблона

enum MyEnum 
{ 
    ONE = 1, TWO, THREE 
}; 

template<class T> 
void func() 
{ 
    cout << T::TWO << endl; 
} 

int main() 
{ 
    func<MyEnum>(); 
}; 

Это работает, но я получаю предупреждение: «предупреждение C4482: нестандартное расширение используется: перечисление„MyEnum“используется в уточненном имени»

Как это сделать, не получив предупреждения

+1

'enum E1 {ONE, TWO}; enum E2 {ONE, TWO}; 'дает" противоречивое объявление 'ONE', как я ожидал бы - значения' enum E1' не попадают в пространство имен 'E1'. Что вы ожидаете? – delnan

+1

'TWO' определен в вашем' MyEnum', который не является частью класса или пространства имен в том, что вы показали. enum не объявляют область действия и, следовательно, не разрешают использование оператора области. –

+0

, но это то, что я хочу сделать, я хотел бы иметь возможность передавать как E1, так и E2 и получать разные значения при печати. ​​ – hidayat

ответ

5

Enum здесь немного сложнее. Тип ONE и TWO будут во внешнем пространстве имен. Поэтому добавление типа к имени приводит к предупреждению. Вы можете просто удалить Классификатор

template<class T> 
void func() 
{ 
    cout << TWO << endl; 
} 

С ДВУМЯ известен во внешнем пространстве имен. Вы также можете просто переместить свой enum в какую-то закрывающуюся структуру.

struct EnumContainer 
{ 
    enum MyEnum 
    { 
     ONE = 1, TWO, THREE 
    }; 
}; 

template<class T> 
void func() 
{ 
    std::cout << T::TWO << std::endl; 
} 

int main() 
{ 
    func<EnumContainer>(); 
}; 

Теперь компилятор должен быть в порядке.

+0

«Тип ONE и TWO будет во внешнем пространстве имен."- не типы, а в стандартном они * перечисляющие * :-) –

+2

в C++ у вас есть' enum struct MyEnum {ONE, TWO}; ', см. http://en.wikipedia.org/wiki/C%2B % 2B0x # Strongly_typed_enumerations –

1

Хотя было бы неплохо использовать перечисление в качестве параметра шаблона и распознать каждое отдельное перечисление отдельно, как вы его написали, этого не произойдет. Вместо этого, я могу предположить, что вы заявляете следующее:

template<MyEnum T> 
void func(){ 
    std::cout << T << std::endl; 
} 

Самое замечательное C++ является то, что способ шаблоны структурированы дает вам токарной полную систему. Следовательно, вам не нужен отдельный вызов, подобный этому, поскольку вы объявили, что получили каждое индивидуальное значение перечисления. Вы можете создать отдельную функцию для каждого значения , когда вам это нужно, и только тогда, когда вам это нужно..

Теперь, перейдя к другой проблеме вашего вопроса, как прокомментировал @delnan, у вас не может быть двух разных имен с таким же именем. Вы можете, однако, есть класс с переменной-члена называется TWO такие, что:

struct Foo{ 
    int TWO; 
}; 

struct Bar{ 
    int TWO; 
}; 

template<typename T> 
void func(){ 
    std::cout << T::TWO << std::endl; 
} 

Надежда, что помогает.

+0

Он также может объявить перечисление как член структуры, чтобы он мог иметь перечисление, определенное несколько раз (в разных областях). Хотя я бы поставил под вопрос, почему это было бы желательно в большинстве случаев. –

+0

Я сомневаюсь, что это компилируется . 'typename' используется для типов,' TWO' - это атрибут, для которого требуется экземпляр класса .... –

+0

@Mathieu M. Вы правы, изменились. – wheaties

1

Представления (pre C++ 0x) рассматриваются как целые типы.

На самом деле, обозначение MyEnum :: TWO - мусор: нет класса или пространства имен MyEnum. Имена ONE, TWO и THREE приводятся в пространство имен, где определено перечисление [в данном случае - глобальное пространство имен].

Вы должны получить ошибку, такую ​​как TWO is not a member of MyEnum.

Один из способов эмулировать поведение - это поместить его в структуру или класс, как и другие.

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