2009-05-12 3 views
27

저는 열거 형의 작업을 이해하기 위해 C++ 표준을 약간 읽으려고했습니다. 실제로 원래 생각했던 것보다 더 많은 것이 있습니다.C++에서 C++ 열거 형의 기본 형식 0x

범위가 지정된 열거 형의 경우 enum-base 절 (모든 정수 유형이 될 수 있음)이 지정되지 않은 경우 기본 형식이 int 인 것이 분명합니다. 범위가 지정되지 않은 열거 들어

enum class color { red, green, blue}; // these are int 

, 작동하고있을 필요하지 않는 한이, int 형보다 큰 수 없음을 어떤 정수 계열 형식이 될 수있는 기본 유형처럼 보인다.

enum color { red, green, blue}; // underlying type may vary 

범위가 지정되지 않은 enumarations의 기본 형식이 표준화되어 있지 않기 때문에, 하나의 직렬화 인스턴스를 처리하는 가장 좋은 방법은 무엇입니까? 지금까지 나는 int에 직렬화를 쓰고 읽을 때 스위치에 내 enum 변수를 설정할 때 int으로 변환했습니다.하지만 조금 어색한 것처럼 보입니다. 더 좋은 방법이 있습니까?

enum color { red, green, blue }; 
color c = red; 
// to serialize 
archive << (int)c; 
// to deserialize 
int i; 
archive >> i; 
switch(i) { 
    case 0: c = red; break; 
    case 1: c = green; break; 
    case 2: c = blue; break; 
} 
+2

열거 클래스 만 C++ 0X ... – Klaim

+2

+1,이 질문은 -1ed 이유를 모르겠 ... –

+1

아마도 질문자는 분명히 기존 및 제안 된 표준 문서를 구별 할 수 없기 때문에? –

답변

5

나는 C++ 0x 내용을 읽지 않았으므로 그것에 대해 언급 할 수 없습니다.

직렬화의 경우 열거 형을 다시 읽을 때 스위치가 필요하지 않습니다. 열거 형으로 변환하면됩니다.

그러나 스트림에 쓸 때 캐스팅하지 않습니다. 왜냐하면 나는 종종 값이 쓰여지는 것을 잡을 수 있도록 열거 형에 대해 연산자 < <을 쓰고 싶기 때문입니다. 그렇지 않으면 문자열을 대신 써낼 수 있습니다.

enum color { red, green, blue }; 
color c = red; 

// to serialize 
archive << c; // Removed cast 

// to deserialize 
int i; 
archive >> i; 
c = (color)i; // Removed switch 
+1

enum에 연산자 <<를 쓰는 것에 감사드립니다. 나는 나 자신을 생각해야했다. – criddell

+0

귀하의 의견에, 당신은 연산자 <<를 작성 언급하고 위의 코드가 올바르게 그 과부하와 함께 작동합니다 이해합니다. 그러나 <<가 오버로드되지 않았다면 직렬화하기 전에 int를 캐스팅해야합니다. 맞습니까? – criddell

+0

아니요. 만약 당신이 그렇게하고 열거 연산자를 추가했다면 << int로 캐스팅하지 않을 것입니다. 열거 형을 작성하고 캐스트를 제거하는 코드의 모든 위치를 찾아야합니다. – markh44

16

열거 클래스 그것은 C++ 03에 존재하지 않는하는 C++0x 기능입니다.

표준 C++에서 열거 형은 형식에 안전하지 않습니다. 열거 유형이 다른 경우에도 효과적으로 정수입니다. 이것에 의해, 다른 열거 형의 2 개의 enum 치를 비교할 수 있습니다. C++ 03이 제공하는 유일한 안전성은 하나의 enum 유형의 정수 또는 값이 암시 적으로 다른 enum 유형으로 변환되지 않는다는 것입니다. 또한 기본 정수 유형 인 정수의 크기를 명시 적으로 지정할 수 없습니다. 그것은 구현 정의됩니다. 마지막으로 열거 형 값은 둘러싼 범위로 범위가 지정됩니다. 따라서 두 개의 개별 열거 형이 일치하는 멤버 이름을 가질 수 없습니다. C++ 0x는 이러한 문제가없는 열거 형의 특별한 분류를 허용합니다. 이것은 (위키 피 디아 기사에서) 열거 형 클래스 선언

예를 사용하여 표현된다

(나는 원래의 질문의 일부가 아닌 생각) 직렬화 부분에 관해서는
enum Enum1;     //Illegal in C++ and C++0x; no size is explicitly specified. 
enum Enum2 : unsigned int; //Legal in C++0x. 
enum class Enum3;    //Legal in C++0x, because enum class declarations have a default type of "int". 
enum class Enum4: unsigned int; //Legal C++0x. 
enum Enum2 : unsigned short; //Illegal in C++0x, because Enum2 was previously declared with a different type. 

, 나는에 좋아 열거 형 항목은 문자열 동작 (및 뒤로)으로 변환하는 도우미 클래스를 만듭니다. 열거 형 항목은 코드 비헤이비어를 변경하지 않고도 재정렬 될 수 있기 때문에 일반적으로 이름이 나타내는 정수 값보다 안정적입니다.

1

마찬가지로 enum class color :이 C++/CLI (C++ .NET) 또는 향후 C++ 0x 코드입니까?

직렬화의 경우 복사 할 바이트 수를 알기 위해 sizeof(color)으로 열거 형 크기를 얻을 수 있습니다.

14

내 오래된 것은 너무 어수선하기 때문에 새로운 대답을 만들기로 결정했습니다. 어쨌든 뭔가에 대한 C++ (11),이 하나를 사용하여 열거의 기본 유형을 얻을 수있는 곳을 말하고 싶은 :

std::underlying_type_t<E> 

그리고 관심을 위해, 과부하 해상도 아이디어

. 그러나 @lothar에서 제안한대로 이름을 사용하여 열거 형을 저장하십시오.

과부하 해결은 열거 형에서 기본 유형의 모든 값을 나타낼 수있는 int, unsigned int, long, unsigned long의 첫 번째 프로모션이 있다는 사실에서 기인합니다. 다른 정수 유형으로의 변환은 낮은 순위이며 과부하 해결은 선호하지 않습니다.

char (& f(int))[1]; 
char (& f(unsigned int))[2]; 

char (& f(long))[3]; 
char (& f(unsigned long))[4]; 

char const* names[] = { 
    "int", "unsigned int", 
    "long", "unsigned long" 
}; 

enum a { A = INT_MIN }; 
enum b { B = UINT_MAX }; 
enum c { C = LONG_MIN }; 
enum d { D = ULONG_MAX }; 

template<typename T> void print_underlying() { 
    std::cout << names[sizeof(f(T()))-1] << std::endl; 
} 

int main() { 
    print_underlying<a>(); 
    print_underlying<b>(); 
    print_underlying<c>(); 
    print_underlying<d>(); 
} 

그리고 여기 하나 인쇄 : 직렬화 데이터의 크기가 일정하지 폭 때문에

int 
unsigned int 
int 
unsigned int 

그것은 (이 직렬화 문제에 특히 관심이 아니에요을,이 때 문제가 발생할 수 있습니다 열거 형 및 기본 유형이 변경됨) 일반적으로 열거 형 전체를 저장하는 유형을 파악하는 것은 일반적으로 흥미 롭습니다. 건배!

+0

'std :: underlying_type'은 올바른 타입을 얻기위한 최선의 해결책입니다. 작은 수정 : 도우미 **'std :: underlying_type_t '**는 ** C++ 14 **를 통해 사용할 수 있습니다. ** C++ 11 ** ** 대신 ** std :: underlying_type :: type' **을 사용해야합니다. – ollo

5
#include <type_traits> 

enum a { bla1, bla2 }; 
typedef typename std::underlying_type<a>::type underlying_type; 

if (std::is_same<underlying_type, int>::value) 
    std::cout << "It's an int!" << endl; 
else if (std::is_same<underlying_type, unsigned int>::value) 
    std::cout << "It's an uint!" << endl; 
+2

실제로 코드 블록을 역류시키는 것이 아니라 실제로 무엇을하고 있는지 설명하기 위해 텍스트를 사용하는 것이 일반적입니다. –

+0

설명에 찔러 보겠습니다. 이 코드는 컴파일러에서 열거 형의 기본 유형을 파악할 수 있도록 약간의 템플릿 마법을 사용합니다. 직렬화를위한 기본 유형을 파악하는 방법을 물어 보았고이 코드를 사용하면됩니다. – criddell

관련 문제