공부/C || C++

C++ 11 enum class

sudo 2021. 7. 10. 00:42

C++ 11부터는 enum class라는 syntax를 지원한다. 이 enum class는 기존의 enum의 문제점을 보완하고자 나온 syntax이다. enum은 사용자 정의 타입임에도 정수형과 호환이 가능하다. 예를 들어서 

enum Color 
{
    RED,
    GREEN,
    BLUE 
};

int main()
{
    int rgb = RED;
}

또한 enum은 정의하면 enum내에서가 아닌 enum이 포함된 스코프 내에서 정의되기 때문에 같은 스코프 내에서 서로 다른 enum 블록에서 정의한다고 하더라도 이름이 겹치면 재정의된 것으로 보고 오류가 난다. 예를 들어서

int main()
{
    enum Color
    {
        RED,
        BLUE,
        GREEN, // duplicated!
    };

    enum Color2
    {
        GREEN, // duplicated!
        YELLOW,
        WHITE
    };
}

이렇게 서로 다른 enum문이라고 하더라도 GREEN이 두번 정의된 것으로 본다.

 

또한 enum은 사용자 정의 타입을 만든 셈인데, 이렇게 사용자 정의 타입을 만들었는데 정수형과 아무 문제없이 호환된다. Type safe하지 않다는 의미다. 또한 이런 것도 문제없이 컴파일 된다.

enum Color
{	
    RED,
    BLUE,
    GREEN,
};

enum Direction
{
    LEFT,
    RIGHT
};

int main()
{

    Color color = RED;
    Direction dir = LEFT;
    if (color == dir)
    {
        std::cout << "color is same as direction" << std::endl;
    }

}

타입도 다르고 변수에 저장된 내용도 다르지만 비교도 가능하고 심지어 같다고 한다. 이런 이유는 실제로는 그냥 정수형 상수로 지정되어 있기 때문이다. 참고로 enum은 다음과 같이 정수를 할당해줄 수 있다.

enum Direction
{
    LEFT,
    RIGHT
};
enum Color
{
    RED,
    BLUE = 30,
    GREEN,
};

int main()
{
    Direction Left = LEFT;
    Direction Right = RIGHT;
    
    std::cout<<"LEFT: "<<Left<<std::endl; // 0
    std::cout<<"RIGHT: "<<Right<<std::endl; // 1

    Color Red = RED;
    Color Blue = BLUE;
    Color Green = GREEN;
    
    std::cout<<"RED: "<<Red<<std::endl; // 0
    std::cout<<"BLUE: "<<Blue<<std::endl; // 30
    std::cout<<"GREEN: "<<Green<<std::endl; // 31
}

아무런 상수를 할당하지 않으면 0부터 시작하고, 할당한다면 할당한 수부터는 1씩 증가한다.

 

다시 enum의 문제점으로 돌아와보자. enum은 위에서 언급한 문제들 때문에 C++ 11부터는 enum class를 지원하고 enum말고 enum class를 사용하도록 권고한다. enum class은 다음 코드처럼 쓸 수 있다.

 

enum class Job
{
    Knight,
    Magician,
    Archer
};

enum class Coffee
{
    Americano,
    Latte,
    Mocha,
};

enum class Job2
{
    Archer,
    Warrior
};

int main()
{
   // Job job = Archer; // Not allowed

    Job job2 = Job::Magician;
    Coffee coffee = Coffee::Mocha;
    
    //if (job2 == coffee)  Not allowed
    //{
    //    std::cout << "Job is same as Coffee" << std::endl;
    //}

}

먼저 눈에 띄는 점은 Job에도 Archer가 있고 Job2에도 Archer가 있는데 문제가 없다. 이것은 두개가 서로 별개의 enum 스코프 내에서 정의된 것이기 때문이다. 마치 서로 다른 함수 내에서 같은 이름의 지역변수를 선언하는건 문제 없듯이. 그리고 이전 enum과 달리 enum class는 말 그대로 class이기 때문에 scope 연산자(::)를 사용해야 한다. 마지막으로 enum에서 허용됐던 서로 다른 타입끼리의 비교가 허용되지 않는다. 

 

Reference

https://unikys.tistory.com/376

 

[C++11] enum과 enum class

* 최근에 C++로 코딩하면서 옛날에 머물러있었던 C++ 개발 실력이었기 때문에 새로 보는 내용들이 아주 많다. 지금은 그냥 여기서 그렇게 하고 있으니까 따라한다는 마음이 크지만, 조금씩은 왜

unikys.tistory.com

https://boycoding.tistory.com/180

 

C++ 05.05 - enum class

05.05 - enum class 열거형(enum)은 C++ 에서 고유한 유형이지만, 형식이 안전하지 않으므로 어떤 경우에는 이해가 되지 않는 작업을 수행할 수 있다. #include int main() { enum Color { RED, // RED is placed..

boycoding.tistory.com