lundi 27 février 2017

Macro generating a valid name of template-class static instance

Background

I am tinkering with polymorphic serialization and deserialization in C++. For that purpose I use a static map: [type id-string] -> [type factory function].

Each type has to be registered in this map and I would like to do it at compile-time.

Approach

The naïve approach is:

/// Creates a concrete serializable type provided as a template parameter
template <typename T>
ISerializable* createSerializable() { return new T; }

/// Factory that registers a serializable type T
template <typename T>
struct SerializableFactory
{
    SerializableFactory(const char* type_name)
    {
        // registerType adds a type_name->factory_function entry to the map
        registerType(type_name, createSerializable<T>);
    }
};

Registering the types is done with the macro:

/// Macro that registers the type at compile-time using a static factory instance
#define REGISTER_TYPE(T)                                                   \
    static SerializableFactory<T> global_##T##Factory(#T);

For example REGISTER_TYPE(ArbitraryClass) will become:

static SerializableFactory<ArbitraryClass> 
    global_ArbitraryClassFactory("ArbitraryClass");

Problem

Unfortunately this will not work for ArbitraryClass<int> bacause <, > are not allowed to be used in identifier.

Question

Is there a good work-around to achieve registering arbitrary template type this way?

Alternatives

I considered the following alternatives (each has disadvantages):

  • Registering types run-time: looks less elegant, requires more effort from the serialization user;
  • RTTI: requires RTTI to be enabled, gives no guarantees that different types will have always different hashes/names (very unlikely of course, but still);
  • Asking the user to provide an alias name: less elegant, more effort from the serialization user

Aucun commentaire:

Enregistrer un commentaire