Enum class
###DESCRIPTION_HERE###
enum class
enum class
는 기존 enum
의 문제점들을 보완하기 위해 등장하였다.
scope
enum
에 선언된 내용은 enum
과 같은 scope 범위를 갖는다.
1 | enum Color { black, white, red }; |
enum class
에 선언된 내용은 그 내부로 scope가 제한된다.
1 | enum class Color { black, white, red }; |
implicit conversion
enum
은 암묵적으로 정수 타입으로 변환된다.
1 | enum Color { black, white, red }; |
enum class
는 암묵적으로 형변환되지 않기 때문에 위와같은 실수를 막을 수 있다.
1 | enum class Color { black, white, red }; |
만약 형변환이 필요하다면 static_cast
와 같은 명시적 형 변환을 해야한다.
묵시적 형변환을 제한하는 enum class
는 비트연산에서 사용하기에 상당히 까다롭다.
1 | using UserInfo = |
UserInfo
에서 이메일 주소를 가져오는 방법은 아래와 같다.
1 | UserInfo info; |
사용자입장에서 UserInfo
의 비트필드 1에 어떤 정보가 있는지 헷갈릴 수 있다.
enum
을 이용해서 이를 좀더 명확히 할 수 있다.
1 | enum UserInfoFields { uiName, uiEmail, uiReputation }; |
이런 연산이 가능한 이유는 enum
은 명시적 형변환을 지원하기 때문이다.
만약 enum class
를 사용한다면 아래처럼 코드가 복잡해질 것이다.
1 | enum class UserInfoFields { uiName, uiEmail, uiReputation }; |
enum class
를 받아서 std::size_t
를 반환하는 함수를 작성하면 문제가 나아질 수 있다.
먼저 std::get
은 템플릿이다. 몇 번째 비트 필드를 가져올지는 템플릿 인자로 전달된다. 따라서 우리가 작성하는 함수는 컴파일 타임에 결과를 반환하는 constexpr
로 작성해야 할것이다.
또 범용성을 위해 모든 enum class
타입을 받도록 템플릿 함수가 되어야 한다. 그리고 그 반환 타입 역시 std::size_t
대신 해당 enum class
의 underlying_type이 되는것이 바람직 하다. 마지막으로 이 함수는 예외를 던지지 않을 것이므로 noexcept
로 선언되어야 한다.
1 | template <typename E> |
C++14의 alias declaration을 사용하면 반환타입을 간소화 할 수 있다.
1 | template <typename E> |
C++14가 지원하는 auto
반환 타입을 사용할 수도 있다.
1 | template <typename E> |
작성한 함수를 사용하면 튜플의 비트 필드에 다음과 같이 접근할 수 있다.
1 | auto val = std::get<toUType(UserInfoFields::uiEmail)>(info); |