2010-04-15 3 views
2

열거 형을 int로 자동 직렬화하는 방법이 있습니까? 때마다 나는 새로운 열거 형을 정의하고 컴파일러가 운영 < <과는 >> 정의되지 않은 불평자동으로 enum을 int로 직렬화하는 방법이 있습니까?

std::stringstream stream; 
stream << myenum1; 
stream >> myenum2; 

물품. 열거 형을 일반 int로 처리하도록 컴파일러에 지시하는 방법을 알고 있습니까?

실제로 문제가 더 어려워지는 이유는 실제로 직렬화가 템플릿 안에 있다는 것입니다. 이런 식으로 뭔가?.

template <typename T> 
void serialize(const T& value) 
{ 
    std::stringstream stream; 
    stream << value; 
} 

그래서 내가 아마 어떻게 든 그것을 전문으로 할 수있는 모든 캐스트 :( 를 추가 할 수 없습니다

감사합니다

답변

4

유형이 부스트의 TypeTraits (is_enum)로 enum인지 확인할 수 있습니다.

그럼 당신은 enable_if/disable_if 이것을 결합 할 수 있습니다 :

template <class T> 
typename boost::disable_if<boost::is_enum<T> >::type serialize(const T&); 

template <class T> 
typename boost::enable_if<boost::is_enum<T> >::type serialize(const T&); //use casts here 

그러나, 당신이 주어진에 대해 특정 과부하를 작성하지 않는 한 (주어진 값이 주어진 열거 유효 여부를 확인하는 것이 가능하지 않을 것이다 enum 유형).

+0

다른 템플릿 특성을 사용하여 유효성을 확인할 수 있습니다 – James

+0

@Autopulated : 어떻게 생겼습니까? (또한 열거 형 enum 상수와 열거 형의 유효한 값이 일치하지 않습니까?) – UncleBens

+0

자, 열거 형을 사용하는 방법에 따라 다르지만 일반적으로 각 열거 형의 특성에 과부하가 걸리고 각 열거 형에서 max_value enum 값과 같은 것을 사용합니다 유형. 특성을 사용하는 장점은 모든 것을 허용하거나 원하는대로 미리 정의 된 범위를 허용하는 기본값을 가질 수 있다는 것입니다. – James

1

는 예를 들어, 정수로 열거 캐스팅 사용하려고 했 ?

+0

템플릿이있는 코드 안에 있기 때문에 캐스팅 할 수 없습니다. 더 명확하게 질문을 업데이트했습니다. – FireAphis

+3

열거 형의 기본 유형이 반드시 'int'일 필요는 없습니다. 자세한 내용은 [this] (http://stackoverflow.com/questions/1122096)를 확인하십시오. –

+0

@FireAphis : 캐스팅해야하는 유형 인 템플릿에 전달하는 두 번째 유형을 사용할 수 없습니까? –

1

static_cast<int>(enumX)는 일반 INT의의 같은 열거 형을 치료하는 컴파일러에게 할 수있는 방법을 알고 계십니까?

형식 안전하지 않으므로 적어도 >>는 사용할 수 없습니다 (enum에 int를 할당하면 형식이 안전하지 않습니다).

당신이 할 수있는 한 가지 일은 각 열거 형에 대해 >> 및 < < 연산자의 과부하를 제공하는 것입니다. 그러면 전송이 수행됩니다. 이것은 각 열거 형에 대해 수행 할 작업입니다. >>/< < (사용하는 장소를 편집 할 수 없으므로 여기에서 특히 편리합니다) .

+0

정확히 내가 피하기를 원하는 것입니다 - 열거 형을 추가 할 때마다 연산자를 추가하십시오. 그것을 할 일반적인 방법이 아닌가요? – FireAphis

+1

SFINAE를 사용하면 is_enum을 사용하여 열거 형을 검색 할 수있는 연산자 템플릿을 제공 할 수 있습니다 (http://msdn.microsoft.com/en-us/library/bb982983.aspx 참조). 이것이 얼마나 효과적 일지와 내가 현재 할 수없는 많은 것을 더 열심히 생각해야만하는 것입니다. – Suma

0

기본 유형 (예 : unsigned short)을 명시 할 수 있으므로 C++ 0x에서 더 좋아질 것입니다.

예를 들어 모든 열거 형 값을 int 내에 저장할 수 있다고 가정 할 경우 규칙을 사용해야합니다.이를 직렬화하고 int로 역 직렬화 한 다음 다시 변환 할 수 있습니다.

std::stringstream stream; 
stream << 1 << 2; 
int a; 
stream >> a; 
assert(a == 12); 

일반적으로 직렬화 알려진 크기의 일부 이진 표현을 복용 (또는 따라 크기를 직렬화) 포함 :

다른 문제

물론 당신의 직렬화 루틴입니다. 당신이 자신을 처리하지 않으려면, 도서관이 있습니다 :

  • Boost.Serialization
  • Google.ProtocolBuffers

그리고 모두 일반 텍스트와 이진 표현이 (일반 텍스트입니다 디버깅하기 쉬운 방법).

3

출력의 경우 << 연산자는 enum 유형을 int 또는 long에 가장 근접하게 올립니다. (§5.8/1, 4.5/2) 당신은 어떤 문제도 있어서는 안되며, 나는 GCC 나 Comeau를 가지고 어떤 것도 생산할 수 없었다. 틀 렸으면 고쳐줘.

입력의 경우 템플릿 함수를 작성하고 명시 적으로 인스턴스화 된 클래스 내에 숨김으로써 암시 적 인스턴스화를 비활성화 할 수 있습니다.

template< class E > 
struct enum_traits { 
    friend std::istream &operator>> (std::istream &is, E &e) { 
     long i; // or intmax_t, whatever 
     std::istream &r = is >> i; 
     e = E(i); 
     return r; 
    } 
}; 

enum my_enum { a, b, c }; 
template class enum_traits<my_enum>; // explicit instantiation 
    // "matching declaration" per 7.3.1.2/3: 
std::istream &operator>> (std::istream &, my_enum &); 

이것은 GCC와 Comeau를 전달합니다. 네임 스페이스와 ADL을 더 편리하게 사용할 수있는 방법을 찾을 수 없습니다. (대체 솔루션은 모든 열거 자에 대한 선언을 사용합니다.)

그러나 두 개의 상용구 선언은 매크로로 래핑 될 수 있으며, 어떤 경우에는 전체 함수를 다시 쓰는 것보다 낫습니다!

+1

2 년 후 : C++ 11 범위 지정 열거자는 암시 적으로'<<'로 변환하지 않으므로 출력과 동일한 패턴을 입력으로 사용합니다. UncleBen의 답은 사용자 정의 클래스에 의존하지 않으므로 엄격하게 표준을 따르지 않습니다. 또 다른 유사한 템플리트는 충돌을 일으키지 만, 특정 enum 유형에 대한 단순한 과부하는 아무런 문제가 없습니다. – Potatoswatter

관련 문제