프로그래밍 일반 2014. 4. 8. 19:15

C++ 11 enum class

웹 컴파일러 링크 : http://melpon.org/wandbox/


 기존 enum은 암시적으로 int형으로 형변환 되기 때문에 enum이 정수로써 작동되기를 원하지 않을 때 오류를 발생 시킬 수 있다.

허용되는 범위 밖에서도 열거 이름들을 사용할 수 있었기 때문에 이름간의 충돌이 발생한다.


그러나 새로운 enum class는 타입과 정의 범위가 명확하다.



enum Alert { green, yellow, election, red };  // 이전의 enum

enum class Color { red, blue };    // 범위가 정해져있고, 타입이 잘 정해진 enum

// 이를 포함하고 있는 범위 바깥에서는 열거형을 사용 불가

// int 로 암시적으로 변환되지 않는다.

enum class TrafficLight { red, yellow, green };



Alert a = 7;             // 오류 (모든 C++ 버전에서)

Color c = 7;            // 오류 (int 에서 Color 로 변환 불가)

int a2 = red;              // 가능 (Alert 에서 int 로 변환 가능)

int a3 = Alert::red;     // C++ 98 에서는 오류. C++ 11 에서는 가능

// vs 2008 ver. 9.0.30729.1 sp 에서 warring


int a4 = blue;         // 오류 : blue 가 범위에 없다

int a5 = Color::blue; // 오류 : Color 에서 int 로 변환 불가능

Color a6 = Color::blue; // 가능

새롭게 도입한 열거형의 이름이 "enum class"인 이유는 전통적인 enum의 특징들[각주:1]과 클래스의 특징[각주:2]을 합친 형태이기 때문이다. enum의 타입 자체를 명확하게 정의하면 열거형의 크기를 보장하고, 다른 것들과 쉽게 같이 사용할 수 있다.


enum class Color : char { red, blue };             // 함축된 표현

enum class TrafficLight { red, yellow, green }; // 디폴트로 내장 타입은 int 로 처리된다.

enum E { E1 = 1, E2 = 2, Ebig = 0xFFFFFFF0U };     // E 의 크기가 얼마나 클까요?

// 이전의 규칙에 따르면 -

// 구현에 따라 다르다(implementaion defined)

enum EE : unsigned long { EE1 = 1, EE2 = 2, EEbig = 0xFFFFFFF0U }; // 이제 구체적으로 정할 수

있습니다


enum class Color code : char;    // 전방 선언,  VS 2008 에서 사용 가능

void foobar(Color code* p);        // 전진 선언을 사용

// ...

enum class Color code : char { red, yellow, green, blue };  // 정의

// VS 2008 에서 사용 가능


msdn C++ 레퍼런스를 확인하면

enum [tag] [: type] {enum-list} [declarator];   // for definition of enumerated type
enum tag declarator;   				// for declaration of variable of type tag

// 아래의 코드를 한번씩 확인해보자..

enum Alert { green, yellow, election, red = 400000000 }; //enum Alert { green = -1, yellow, election, red = 4000000000 }; //enum Alert : INT64 { green = -1, yellow, election, red = 40000000000 }; // VS 2008에서 사용 가능


enum 의 내장 타입은 반드시 부호 있는/없는 정수 타입이어야만 합니다. 디폴트는 int 입니다. 표준 라이브러리에서 enum class 는 다음과 같은 경우로 사용됩니다.

  • 시스템의 특별한 오류 코드들을 매핑하기 위해서 (enum class errc)
  • 포인터 안정성 표시자(indicator) (enum class pointer safety {relaxed, preferred, strict};)
  • I/O 스트림 오류들 (enum class io errc {stream = 1 }; )
  • 비동기화통신에서의오류처리를위해(enum class future errc {broken promise, future already retrieved,promise already satisfied }; )


참고






  1. 값을 가진 이름들 [본문으로]
  2. 범위를 가진 멤버들과 암시적 변환의 부재 [본문으로]