drewag
drewag

Reputation: 94723

Serialize a class in C++

Is there a way to serialize a class in C++? I am not referring to an instance of a class but the class itself. When deserializing I do not know what class to instantiate to call deserialize on it. I want to be able to somehow determine what class is being represented, instantiate an empty instance of it, and then call deserialize it.

Edit for clarification:

I am creating a key-value structure where each key has a strongly typed value. (Some keys must store a string, others must store ints, and still others may store arbitrary values). I have devised a system where this is enforced by the compiler through templates.

The Key class has two template parameters:

The Value class is a templated class with just the ValueType that has an abstract superclass so that I can wrap any class within it (similar to a boost::any).

Then in my Key-Value structure I have store and retrieve functions that are templated with a ConceptType and a ValueType:

template<UniqueClass, ValueType>
void store( Concept<UniqueClass, ValueType> concept, ValueType value );

Because I am using the same template to describe the value type of the Concept and the passed in value the compiler will complain if they don't match.

I now want to be able to serialize the Key-Value store. Therefore I need to somehow serialize the templated Concept class and then instantiate the correct arbitrary class during deserialization.

I have it so that I can call serialize and all the appropriate objects are asked to serialize themselves, I just don't know what class to instantiate during deserialize to ask to deserialize itself.

Upvotes: 2

Views: 1790

Answers (1)

Synxis
Synxis

Reputation: 9388

Answer updated due to question edit:

What I understand is that you have 0 keys in the container until you add it manually or via deserialization. There are two way for doing this: intrusive and non intrusive.

Intrusive

Let Concept<U,T> inherit from Deserializable:

class Deserializable
{
    public:
        virtual void deserialize(InputStream& s) = 0;
        virtual int getClassId() const = 0;
};

Now, you can identify a class via its id, retrieved using getClassId(). So, next is to create a factory. Here I will use a really simple one, with std::map, to show the point; feel free to use a more sophisticated one.

typedef Deserializable* (*createDeserializableType)();
std::map<int,createDeserializableType> factory;

// ...

factory[id1] = &createMyClass;
// etc...

// ...

// On deserialization
createDeserializable create = factory[idReadFromStream];
if(create)
    create()->deserialize(input_stream);

It means either you have to add a store method for Deserializable or you add a store method to Deserializable (I personally prefer the last method).

Non-intrusive

The idea is to deserialize the key-value the same time you are creating it and adding it:

typedef void (*deserializeFctType)(InputStream&);
typedef int id_type;
std::map<id_type,deserializeFctType> factory;

The deserialize method will store the deserialized type immediately after creating it.

What is not clear in your question is whether the list of accepted list is finite or infinite. Only a finite set of type is "easily" serializable.

Upvotes: 3

Related Questions