2015-11-17

[C++] enum class - 안전하고 쓰기 쉬운 enum

 C++ 03까지의 enum은 여러 가지 문제를 가지고 있었다. 그래서 그 문제들을 해결하기 위해 C++ 11은 enum class라는 것을 새로 만들었다. 이제부터 기존의 enum에 어떤 문제가 있었고, 이것을 enum class에서 어떻게 해결하였는지 살펴볼 것이다.

 우선 기존의 enum은 전방 선언할 수 없었다. 그 이유는 enumerator에 어떤 값이 들어있을지 알 수 없으면 그 크기를 정할 수 없기 때문이다. 하지만 enum class는 underlying type을 명시하지 않으면 int 타입과 같은 크기의 변수로 선언되고, int 값 안에 들어가지 못할 값을 지정하면 컴파일 에러를 발생시킨다.
 만약 int를 벗어난 범위의 값을 사용하고 싶다면, underlying type을 명시해주어야 한다.


 기존 enum의 또 다른 문제는 enumerator의 이름의 범위가 한정되지 않는다는 것이다. 예를 들어 아래와 같은 코드를 보자.

 IO 함수의 결과와 Parse 함수의 결과를 enum으로 표현해 보았다. 하지만 이 코드는 컴파일되지 않는다. IOResultError, OkParseResultError, Ok와 겹치기 때문이다. 이를 해결하기 위해서는 다음과 같이 enumerator의 이름을 다르게 하거나

 아래와 같이 namespace를 이용해야 했다.

   하지만 enum class는 enumerator의 이름이 enum class 안으로 한정되기 때문에 이런 복잡한 과정이 필요 없이 그저 enum class를 선언하여 사용하면 된다.


 무엇보다 기존 enum의 가장 큰 문제는 정수형 변수로 암시적으로 변환되는 약 타입(weak type) 변수라는 것이다. 하지만 enum class는 정수형 변수로 암시적 변환이 되지 않는다. enum class를 정수형 변수처럼 사용하려고 하면 컴파일 에러를 발생시킨다. 만약 정수형 변수로 사용하고 싶으면 static_cast를 이용해 명시적으로 캐스팅해서 사용해야 한다.


 위에서 설명한 대로 기존의 enum은 전방 선언할 수 없고, enumerator 이름의 범위가 한정되지 않고, 정수형 변수로 암시적으로 변환되지도 않는다. 사실 enum의 사용법을 생각해보면 enum class가 올바른 방식이다. 하지만 C++ 11은 backward compatibility를 위해서 기존의 enum을 그대로 두고, enum class를 새로 추가하는 것을 선택했다. 이제는 compatibility를 위해서가 아니면 enum의 존재는 잊고 대신에 enum class를 사용하는 것이 좋다.

댓글 없음:

댓글 쓰기