[Effective Modern C++] 10. 범위 없는 enum보다 범위 있는 enum을 선호하자
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
'Books > Effective Modern C++' 카테고리의 다른 글
[Effective Modern C++] 12. 재정의 함수들은 override로 선언하자 (0) | 2022.09.04 |
---|---|
[Effective Modern C++] 11. 정의되지 않은 비공개 함수보다 삭제된 함수를 선호하자 (0) | 2022.09.03 |
[Effective Modern C++] 9. typedef보다 별칭 선언을 선호하자 (0) | 2022.08.28 |
[Effective Modern C++] 8. 0과 NULL보다 nullptr을 사용하자 (0) | 2022.08.28 |
[Effective Modern C++] 7. 객체 생성 시 괄호(())와 중괄호({})를 구분하자 (0) | 2022.08.28 |
댓글
이 글 공유하기
다른 글
-
[Effective Modern C++] 12. 재정의 함수들은 override로 선언하자
[Effective Modern C++] 12. 재정의 함수들은 override로 선언하자
2022.09.04 -
[Effective Modern C++] 11. 정의되지 않은 비공개 함수보다 삭제된 함수를 선호하자
[Effective Modern C++] 11. 정의되지 않은 비공개 함수보다 삭제된 함수를 선호하자
2022.09.03 -
[Effective Modern C++] 9. typedef보다 별칭 선언을 선호하자
[Effective Modern C++] 9. typedef보다 별칭 선언을 선호하자
2022.08.28 -
[Effective Modern C++] 8. 0과 NULL보다 nullptr을 사용하자
[Effective Modern C++] 8. 0과 NULL보다 nullptr을 사용하자
2022.08.28