프로그래밍 일반 2014. 10. 22. 18:28

enum 범위 한정 기법과 보다 안전한 문자열 표현

C++ 11 이전 버전의 열거형은 허용범위 밖에서 열거형 이름을 사용할 수 있기 때문에 이름 충돌 문제가 발생한다.


참고 : C++ 11 enum 스펙


일반적으로는 문제가 되지 않지만 통합 빌드(Unity Build) 환경에서는 골치 아픈 문제이기도 하다.


이런 문제는 namespace를 이용해서 피해갈 수 있다.


namespace EType

{

           enum Type

           {

               Null

               , Guerrilla

               , Always

               , MiniDuration

               , CubePiece

               , Discount   

           };

}

범위를 설정하고 내부적으로 열거형의 이름은 Type을 사용한다.


이렇게 사용하면 이름 중복을 피하기 위해 무리해서 이름을 작성할 필요도 없어진다.


eType_Guerrilla

, eType_Always


이름충돌을 피하기 위한 구분자_사용하는 이름, 

.....


만약 클래스 내부에서 사용하는 열거형인 경우에는 

struct EType

{

           enum Type

           {

               Null

               , Guerrilla

               , Always

               , MiniDuration

               , Max

           };

};

이런 식으로 열거형의 범위를 한정할 수가 있다.


위에서 설명한 기법들은 언리얼 엔진 프로그래밍 가이드에 나와있는 old style 표기법이다. 만약 컴파일러가 지원한다 enum class를 사용하도록 한다.


여기에 추가로 열거형을 스트링으로 표현하고 싶을 때 어떻게 하면 좋은지 설명하도록 하겠다.


일반적으로 열거형을 선언한 후 코드 어딘가에 스트링 표현식을 작성할 것이다.


... 코드 어딘가 열거형 스트링

TCHAR* szTypeString[] = {

 _T("Null")

, _T("Guerrilla")

, _T("Always")

, _T("MiniDuration")

, _T("Max")

};

 

... 코드 어딘가에서 출력

for (int i = EType::Null; i < EType::Max; ++i)

{

           출력함수(szTypeString[i]);

}

이런 방식은 열거형이 변경될 때마다 항상 스트링도 수정해야하는데 최악의 경우 프로그램을 죽이는 버그를 만들 수도 있다.


컴파일러는 위의 위험 사항을 알려주지 않는다.


디파인 함수를 이용해서 스트링으로 바꾸는 기법은 예전에 한번 설명한 적이 있는데


참고 : 열거형 스트링 표현


아래와 같은 코드는 열거형의 범위를 한정하고 문자열로 표현하는데 보다 안전하다.


#if !defined(DO_TEXT)

#define DO_TEXT(e)    L#e,

#endif


#if !defined(DO_ENUM)

#define DO_ENUM(e)    e,

#endif


namespace EType

{

#define DEF_EType(NAME) \

                     NAME(Null) \

                     NAME(Guerrilla) \

                     NAME(Always) \

                     NAME(MiniDuration) \

                     NAME(CubePiece) \

                     NAME(Discount)

 

           enum Type

           {

                     DEF_EType(DO_ENUM)

           };

 

           inline const TCHAR* GetConvertSring(EType::Type type)

           {

                    const TCHAR* szString[] = {

                                DEF_EType(DO_TEXT)

                     };

 

                     return szString[type];

           }

}


프로그래밍 일반 2013. 6. 5. 14:19

enum 간단한 코드로 의미있는 에러코드 출력하기

프로그램이 실행되는 도중에 에러코드가 숫자로 출력되면 해당 에러코드가 어떤 의미인지 코드를 찾아봐야하는 번거로움이 있다.


디파인 함수를 잘 이용하면 단순한 코드로 해당 문제를 상당부분 해소할 수 있다.



샘플 코드 


#define DO_TEXT(e) L#e,

#define DO_ENUM(e) e,


#define CRYPTO(NAME) \

NAME(ERROR_AUTH_SUCCESS) \

NAME(ERROR_AUTH_DECODING_FAILURE) \

NAME(ERROR_AUTH_TOKEN_IS_NOT_VALID)


enum eERROR_CJIJCRYPTO {

CRYPTO(DO_ENUM)

};



TCHAR* szError_CJIJCrypto[] = {

CRYPTO(DO_TEXT)

};



단점은 enum에 주석을 사용할 수 없는 없다는 점인데 의미있는 문자열을 사용하면 간단히 넘어갈 수 있는 문제이다.