Search code examples
c++c++14template-specializationpure-virtual

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


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?


Solution

  • 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> { /* ... */ };