views:

134

answers:

2

Hello!

As far as I understand, there is no serialization (boost::serialization, actually) support for boost::any placeholder.

Does someone know if there is a way to serialize a custom boost::any entity?

The problem here is obvious: boost::any uses template-based placeholders to store objects and typeid to check if boost::any_cast is appropriate.

So, there is a custom abstract superclass placeholder and custom template-based derived classes, which are created the following way:

template <T> custom_placeholder : public placeholder {
    virtual std::type_info type() const { return typeid(T); }
    virtual ...
};

Obviously, this brings some troubles when even thinking about serializing this stuff. Maybe someone knows some trick to make such kind of serialization (and of course, proper deserialization)?

Thank you

+2  A: 

It is not possible at all, at least for arbitrary types. Note that maybe you could serialize using some tricky code (like finding the size of the elements contained in the any), but the any code relies on the compiler statically putting the any type_code and the proper types inside the placeholder. You surely cannot do that in deserialization in C++, as the type that you'd get from the deserialization is not known at compile time (as required by the newly formed boost::any).

The best solution is to build some kind of specialized any type for the exact types of elements you're going to serialize. Then, you can have special cases for the actual type of element being deserialized, but note that each element type serialization/deserialization has to be phisically written as static C++ code.

PD. Some others suggested using boost::variant as a representation of this specialized type holding the exact types you're going to serialize. You need a way of discerning the exact type on deserialization, though (maybe assigning identifiers to types in the variant).

Diego Sevilla
A specialized type for a know set of types would be called a variant like e.g. [`boost::variant`](http://www.boost.org/doc/libs/1_44_0/doc/html/variant.html) (which obviously only gives the foundation).
Georg Fritzsche
@Georg: Yes, thanks for the hint. I edited the response to reflect that.
Diego Sevilla
+1  A: 

Assuming you have to use boost::any and you cannot switch to variant, a map<type_info const*, string(*)(any)> based solution could get you done.

You have to initialize at runtime such a map with all the types you plan to use. Of course, you can use something along the lines of

template <typename T>
struct any_serializer
{
    static string perform(any a)
    {
        T const& x = any_cast<T const&>(a);
        stringstream out;
        out << x;
        return out.str();
    }
};

and populate the map with addresses of any_serializer<T>::perform under the key &typeid(T). You can specialize the class any_serializer and use some (ugly) macros to populate the map.

More difficult is of course the deserialization. I haven't had a look at boost::lexical_cast for a while, perhaps it can provide some help. I am afraid that this is totally problem-dependant. However, you only need one function, which takes a string and returns one any. You may also want to prepend your output string with a custom type identifier.

Alexandre C.
That function pointer type should be `string (*)(any)`.
Georg Fritzsche
@Georg: oops fixed thanks
Alexandre C.
Diego Sevilla
@Diego: I don't see the problem. The map is local to the program and is only a mean to dispatch the various serialization routines. What I'd be more concerned about if whether `typeid(T)` always yields objects which can be compared by address. This can be solved with a simple wrapper class which calls `type_info::before` as `operator<`.
Alexandre C.
@Alexandre: I was refering to transfering the map (using typeid's as keys) through a network channel, for example, or being used to be read by different applications running in different architectures or operating systems. This key for the map would be program-dependant, and you'd need a system-independent type identifier, as you added in your edit to the response.
Diego Sevilla
@Diego: Of course, you don't transfer the map... One more point: the serialization routines *should not* be implemented in shared libraries, since this too will likely mess up the `type_info` stuff...
Alexandre C.