How can I improve the design of this serialization mechanism? I'm working on caching library which is intended to work with all types of values.

Values are represented as instances of value_type: value_type holds a std::vector&lt;char&gt; for the raw data, and a uint32_t flags integer value which is used to indicate the format of the stored data.

I would like to make it easy for the users of the library and provided a serialize() method that would convert a C++ type to a value_type so that instead of writing:

// In the line below, serialization::string is an integer constant
value_type value(serialization::string, "My string");


People could just write:

value_type value = serialize("My string");


And somehow the serialize() method would "guess" that the associated integer flag is serialization::string.

I would also make it possible for an user to register his own types and conversions into the serialization mechanism.

I came up with the following code:

/**
 * \brief A default serializer type.
 * \tparam Type The type to serialize.
 */
template &lt;typename Type&gt;
struct serializer {};

/**
 * \brief The base serializer type.
 * \tparam Type The serialized type.
 * \tparam Flags The flags.
 *
 * Derive from this type to enable a new serialization.
 */
template &lt;typename Type, value_type::flags_type Flags&gt;
struct base_serializer
{
    /**
     * \brief The type supported by the serializer.
     */
    typedef Type type;

    /**
     * \brief The flags.
     */
    static const value_type::flags_type flags = Flags;

    static value_type serialize(const type&amp; value)
    {
        return value_type(flags, serializer&lt;type&gt;::serialize_data(value));
    }

    /**
     * \brief Deserialize a value.
     * \param value The value.
     * \return The deserialized value.
     */
    static Type deserialize(const value_type&amp; value)
    {
        if (value.flags() != flags)
        {
            throw boost::system::system_error(serialization::error::invalid_types, serialization::serialization_category(), "deserialization failed");
        }

        return serializer&lt;type&gt;::deserialize_data(value.data());
    }
};

/**
 * \brief Serialize a value.
 * \tparam Type The type.
 * \param value The value.
 * \return The serialized value.
 */
template &lt;typename Type&gt;
value_type serialize(const Type&amp; value) { return serializer&lt;Type&gt;::serialize(value); }

/**
 * \brief Deserialize a value.
 * \tparam Type The type.
 * \param value The value.
 * \return The deserialized value.
 */
template &lt;typename Type&gt;
Type deserialize(const value_type&amp; value) { return serializer&lt;Type&gt;::deserialize(value); }

/**
 * \brief A const char* serializer.
 */
template &lt;&gt;
struct serializer&lt;const char*&gt; : public base_serializer&lt;const char*, serialization::string&gt;
{
    static std::vector&lt;char&gt; serialize_data(type value)
    {
        return std::vector&lt;char&gt;(value, value + strlen(value));
    }
};

/**
 * \brief An overload.
 * \param value A C-string.
 * \return The serialized value.
 */
value_type serialize(const char* value) { return serializer&lt;const char*&gt;::serialize(value); }

/**
 * \brief A std::string serializer.
 */
template &lt;&gt;
struct serializer&lt;std::string&gt; : public base_serializer&lt;std::string, serialization::string&gt;
{
    static std::vector&lt;char&gt; serialize_data(type value)
    {
        return std::vector&lt;char&gt;(value.begin(), value.end());
    }

    static type deserialize_data(const std::vector&lt;char&gt;&amp; value)
    {
        return type(value.begin(), value.end());
    }
};


Do you guys see any improvement ?

Thank you.
You can use an internal traits type to reduce redundancy and complexity.

template&lt; typename serialized &gt;
struct serialize_traits; // no implementation of general case

enum class serialize_style {
    string,
    integral
};

typedef std::vector&lt; char &gt; serial_type; // consider std::string instead

template&lt;&gt;
struct serialize_traits&lt; char * &gt; {
    static const serialize_style style = serialize_style::string;
};

template&lt;&gt;
struct serialize_traits&lt; std::string &gt; {
    static const serialize_style style = serialize_style::string;
};

// Since serializer has no state, I broke this into a free function.
/* It works with both char * and std::string, but uses std::enable_if
   to hide itself unless you specify in serialize_traits that it will work. */

template &lt; typename serialized &gt;
typename std::enable_if&lt; serialize_traits&lt; serialized &gt;::style == serialize_style::string,
serial_type &gt;::type
serialize( serialized const &amp;in ) {
    using std::begin;
    using std::end;
    return serial_type( begin( in ), end( in ) );
}


I need to go so I'll post this now… not tested.