Is there a way to serialize automatically enums as int?

Is there a way to serialize enums automatically as int? Every time I define a new enum and write

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

      

the compiler complains that the <and → operators are not defined. Do you know a way to tell the compiler to treat enums as simple int's?

What complicates the problem is that the serialization is inside the template. Something like that:

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

      

So I can't add any roles :( Maybe I can specialize it somehow?

Thanks.

+2


a source to share


5 answers


You can find out if a type is an enum with boost TypeTraits ( is_enum ).

Then you can combine this with 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

      

However, it will fail to check if the given value is actually valid for the given enumeration (unless you have written a specific overload for the given enumeration type).

+4


a source


For output, the operator <<

will support any type of enumeration up to the nearest match int

or long

. (§5.8 / 1, 4.5 / 2). You shouldn't have any problems and I couldn't produce any GCC or Comeau. Correct me if I am wrong.

For input, you can write a template function and disable the implicit instance by hiding it inside only an explicitly defined class.

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 & );

      



This goes through the GCC and Comeau. I can't find a way to break namespaces and ADL to make it more convenient. (Only an alternative solution involves using a declaration for each enumerator.)

But the two template declarations can be wrapped in a macro, or either way they are better than writing the entire function again!

+3


a source


Have you tried casting numbers to integers using for example static_cast<int>(enumX)

?

+1


a source


Do you know a way to tell the compiler to treat enums as simple int's?

This is not possible (at least for ->), since it would not be type-safe (int assignment to enumeration is not type-safe).

One thing you can do is provide you with operator overloads → and <for each enum, which will do the casting for you. This is what you will do for each enum once, which sounds much better than using it in every place where you use → / <(which is especially handy here, since you cannot edit the places where these operators are used) ...

+1


a source


This will improve with C ++ 0x as you will be able to specify the base type (for example unsigned short

).

Now you need to use a convention, for example, assuming all your enum values ​​can be stored in int

, you can serialize and deserialize it as an int and then convert back.

Another problem is, of course, your serialization routine:

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

      

Serialization usually involves getting a binary representation of a known size (or serializing the size along it). If you don't want to do this yourself, there are libraries:

  • Boost.Serialization
  • Google.ProtocolBuffers

And both have text and binary representation (and plain text is easier to debug).

0


a source







All Articles