Question

I have a Serializer class like this:

class Serializer
{
public:
    // Func 1 (default)
    template <class T>
    void Serialize(T* pValue)
    {
        SerializeInternal(reinterpret_cast<char*>(pValue), sizeof(*pValue));
    }

    // Func 2 (specialization)
    template <> 
    void Serialize<Serializable>(Serializable* pSerializable)
    {
        pSerializable->Serialize(*this);
    }

protected:

    // Implemented by input and output serializers
    virtual void SerializeInternal(char* pData, size_t size) = 0;
};

Now my problem is when I have classes that inherit the Serializable interface they will always be handled by Func 1, even though I want them to be handled by Func 2 (pointers or references doesn't matter they both behave equally). It seems like C++ doesn't recognize that the Serializable interface is inherited unless you clearly specify that:

SerializableClass sc; // Inherits Serializable
InputSerializer s; // Inherits Serializer

s.Serialize(&sc); // Func 1 is called >:(
s.Serialize<Serializable>(&sc); // Func 2 is called

Now as soon as I forget to add <Serializable> somewhere the program of course bugs out, which is pretty annoying.

Is there any way around this?

Was it helpful?

Solution

It seems like C++ doesn't recognize that the Serializable interface is inherited unless you clearly specify that

This is true. If you have some class

class SerializableClass : public Serializable

only SerializableClass, not Serializable, is considered when deducing the T parameter.

If what you need is create two functions, one taking any pointer, the other taking a pointer to anything derived from Serializable, you can create two overloads and use SFINAE to select the narrower one when possible.

template <class T>
typename boost::enable_if_c<!boost::is_base_of<Serializable, T>::value, void>::type foo(T*) { ... }

template <class T>
typename boost::enable_if<boost::is_base_of<Serializable, T>, void>::type foo(T*) { ... }

If you don't want to use boost, you can implement required functionality akin to this.

OTHER TIPS

Use an overload instead of a template specialization!

I found a link explaining how boost::is_base_of works: How does `is_base_of` work?

Apparently they use some pretty fancy template-fu magic to get it to work. I can "easily" write a similar function myself.

When you're not clever enough to solve it yourself, look at the pros ;)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top