728x90
반응형

C++98 스타일의 enum을 이제는 범위 없는 enum이라고 부른다. C++98 스타일의 enum으로 선언된 열거자들에 대해서는 "한 중괄호 쌍 안에서 어떤 이름을 선언하면 그 이름의 가시성은 해당 중괄호 쌍이 정의하는 범위로 한정된다"는 일반적인 규칙이 적용되지 않는다.

그런 열거자 이름들은 enum을 포함하는 범위에 속하며, 따라서 그 범위에 같은 이름이 있으면 안된다. 이러한 이유로 C++98스타일인 enum은 범위 없는 enum이라고 부른다.

enum Color { black, white, red }; // black, white, red는 Color가 속한 범위에 속함
auto white = false; // 오류! 이 범위에 이미 white가 선언되어 있음

범위 있은 enum의 열거자들은 그 안에서만 보인다.

이 열거자들은 오직 캐스팅을 통해서만 다른 타입으로 변환된다. 범위 있는 enum은 enum class 구문으로 선언하기 때문에 enum 클래스라고 부르기도 한다.

enum class Color { black, white, red }; // black, white, red는 Color 범위에 속함
auto white = false; // OK: 이 범위에 다른 "white"는 없음
 
Color c = white; // 오류! 이 범위에 "white"라는 이름의 열거자가 없음
Color c = Color::white; // OK
auto c = Color::white; // OK

범위 있는 enum과 범위 없는 enum 모두 바탕 타입 지정을 지원한다. 범위 있는 enum의 기본 바탕 타입은 int이다. 범위 없는 enum에는 기본 바탕 타입이 없다.

범위 있는 enum은 항상 전방 선언이 가능하다. 범위 없는 enum은 해당 선언에 바탕 타입을 지정하는 경우에만 전방 선언이 가능하다. 메모리를 효율적으로 활용하기 위해, 컴파일러들은 주어진 enum의 열거자 값들의 범위를 표현할 수 있는 가장 작은 바탕 타입을 선택하는 경향이 있다.

그러나 경우에 따라서는 컴파일러가 크기 대신 속도를 위한 최적활르 적용하며, 그런 경우에는 허용되는 가장 작은 바탕 타입을 선택하지 않을 수 있다.

그래도 컴파일러는 크기를 위해 최적화를 적용 할 수 있길 원하며, 이를 가능하게 하기 위해 C++ 98은 오직 enum 정의만 지원하고 enum선언은 허용하지 않는다. 그러면 enum이 실제로 쓰이기 전에 컴파일러가 enum의 바탕 타입을 선택할 수 있기 때문이다.

하지만 enum을 전방 선언 할 수 없으면 몇가지 단점이 생기는데, 가장 주목할만한 것은 아마 컴파일 의존 관계가 늘어난다는 점일 것이다. 그래서 범위 없는 enum은 바탕 타입을 명시적으로 지정해주는 경우에 한해 전방 선언을 할 수 있다.

enum Color: std::uint8_t; // 범위 없는 enum의 전방 선언 바탕 타입은 std::uint8_t
enum Color; // 오류! 바탕 타입 지정 없이 전방 선언 불가능

하지만, 범위 있는 enum의 경우 기본 바탕 타입이 int라고 못박아 두었기 때문에 항상 전방 선언이 가능하다.

enum class Status: std::uint32_t; // Status의 바탕 타입은 std::uint32_t
enum class Color; // OK Color의 바탕 타입은 기본 바탕 타입인 int
728x90
반응형