Define virtual function to be pure in special cases of templated class

77 views Asked by At

I am trying to define a templated base class that defines a virtual interface to be overriden by the user. In some cases it would make sense to have a default implementation of this method but that isn't true for all type parameters. Consider this:

template<typename T>
struct supplier
{
    virtual std::unique_ptr<T> supply(std::istream& moreData) = 0;
};

Now I want to offer the following default implementation given that T is default constructible (std::is_default_constructible):

std::unique_ptr<T> supply(std::istream& moreData)
{
    return std::unique_ptr<T>(new T);
}

The problem is not how to define this function for appropriate T but how to make it appear as a pure virtual function - and thus force an implementation by the user - when it's not defined and like a normal virtual function, if it is.

I think I'm just missing some obvious solution. I tried to specialize struct supplier but that means I'd have to define the rest of the interface two times, so it's definitly not a scaling solution. It also means that I have to provide the rest of the interface two times.

Is there an affordable solution for a rich base class with many virtual functions that may either offer an implementation or be purely virtual?

1

There are 1 answers

2
T.C. On BEST ANSWER

Extract the part you need to specialize into a separate class template, and then inherit from it.

namespace details {
    template<class T, bool = std::is_default_constructible<T>::value>
    struct supplier_base
    {
        virtual std::unique_ptr<T> supply(std::istream& moreData) = 0;
    };

    template<class T>
    struct supplier_base<T, true>
    {
        virtual std::unique_ptr<T> supply(std::istream& moreData)
        {
            return std::unique_ptr<T>(new T);
        }
    };
}

template<class T>
struct supplier : details::supplier_base<T> { /* ... */ };