mercredi 5 décembre 2018

Overload Operator<< for a derived class of a template class

Some bits of context : I am writing a serialization library, and want to keep to a minimum the needed changes for the objects I want to serialize. I found some great examples, such as MetaStuff, but would like to implement it myself for template practice and customization.

My problem :

I want to overload operator<< for my derived classes. The derived classes inherit from a Base class which is a specialized template to themselves. So far, member variable I want to output are public, so let's leave aside the need to declare friend the operator.

template<typename Class>
Class Base {

protected:
    Base(std::string name) : name(name){}

public:
    const std::string name;

    template<typename T>
    static T f(Class& instance);
};

(i simplified a lot to keep only essential elements)

struct Derived : public Base<Derived>{

    Derived():Base<Derived>("Derived"){}

    int a;
    int b;
    bool c;

    static bool registerClass(){ //called by Base<Derived> }
};

I am running into 3 conflicting issues (depending on the solution i give a try) :

Issue 1: ambiguous template resolution

template <typename Class>
std::ostream& operator<<(std::ostream& os, const Class& obj)
{
    os << obj.name << "[ ";
    os << Base::f(obj);
    os << "]";

    return os;
};

Here I run into the ambiguous overload issue. The template function has exact same prototype as the generic one.

Issue 2 : Type Slicing

template <typename Class>
std::ostream& operator<<(std::ostream& os, const Base<Class>& obj)
{
    os << obj.name << "[ ";
    os << Base<Class>::f(obj); 
    //will not compile, since obj is not a Class object anymore.
    os << "]";

    return os;
};

Issue 3 : Function Template Specialization is incorrect

Partial specialization of template function is not possible, and overall function template specialization is to be avoided : compiler will always prefer Base template. (see this nice article)

What is left ?

I am thinking about using solution 2 with static_cast but feel it would be ugly ? I gave a try to a few other solution, which were not worth mentioning.

Has anyone more clues ?

(Since i want modifications to Derived classes to be minimal, i don't want to add a virtual function or so on)

Aucun commentaire:

Enregistrer un commentaire