2

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?

DaedalusAlpha
  • 1,610
  • 4
  • 20
  • 33
  • 1
    This seems to be a very similar question: http://stackoverflow.com/questions/4371699/mixing-template-function-overloading-and-inheritance – UncleBens Dec 08 '10 at 16:47
  • Checked it out and yes it's indeed the same thing. And there the Boost functionality was again the solution. I guess I have to accept there is no pure C++-solution to this (there was a good explanation to why it won't work in that thread as well). – DaedalusAlpha Dec 08 '10 at 17:09
  • The boost solution should contain nothing that is not pure C++. In C++0x, `type_traits` and `enable_if` are parts of the standard library. The latter is trivial to write yourself, `is_base_of` might be trickier. – UncleBens Dec 08 '10 at 17:15

3 Answers3

1

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.

jpalecek
  • 47,058
  • 7
  • 102
  • 144
  • Thanks, but I'm not using Boost and I'm not going to start using it just for this. So a non-Boost solution (if at all possible) would be nice. – DaedalusAlpha Dec 08 '10 at 17:01
  • @DaedalusAlpha: It's fairly trivial to write your own type traits. Most modern Standard libraries include them anyway - they're part of TR1. – Puppy Dec 08 '10 at 17:24
  • The question then is; if Boost use functionality that is already available in C++, then what does it use in is_base_of? The only two reasonable options I've found is a comparison using typeid() which is compiler dependent or using dynamic_cast which is slow as hell. Neither very good solutions. – DaedalusAlpha Dec 08 '10 at 17:44
  • @DaedalusAlpha: See the link I added to the end. Not sure if boost actually uses this (it's a fairly crude way of doing that), but it's one possibility to implement it. – jpalecek Dec 08 '10 at 17:58
  • Thanks just found a similar (same?) implementation which I posted as my own answer: http://stackoverflow.com/questions/2910979/how-is-base-of-works – DaedalusAlpha Dec 08 '10 at 18:11
0

Use an overload instead of a template specialization!

ltjax
  • 15,837
  • 3
  • 39
  • 62
0

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 ;)

Community
  • 1
  • 1
DaedalusAlpha
  • 1,610
  • 4
  • 20
  • 33