Zak
Zak

Reputation: 12613

C++ error: conflicting return type specified for... templated sub-class

Upon first glance, everything seems to be correct, but this code will NOT compile. However, if I were to change the return type of the base class to be double * then it will compile. Can someone explain how/why the compiler does not see the template type "T" as a valid return type.

Base class:

01 template <typename T>
02 class DefaultValueFunctorBase {
03   public:
04     virtual const T operator() (void) const = 0;
05 };

Sub-class:

01 class DblPtrDft : public DefaultValueFunctorBase<double *> {
02   public:
03     DblPtrDft (double default_value_)
04     : DefaultValueFunctorBase<double *>(),
05       _default_value(default_value_),
06       _default_value_ptr(&_default_value)
07     {}
08 
09     const double * operator() (void) const { return _default_value_ptr; }
10 
11   private:
12     const double *_default_value_ptr;
13     const double _default_value;
14 };

ERROR:

DblPtrDft.h:09: error: conflicting return type specified for ‘virtual const double* DblPtrDft::operator()() const’ DefaultValueFunctorBase.h:04: error: overriding ‘const T DefaultValueFunctorBase::operator()() const [with T = double*]’

Upvotes: 1

Views: 2735

Answers (2)

Andy Prowl
Andy Prowl

Reputation: 126412

The problem is that const T should be read as T const, which makes it clear that the const qualifier applies to T. Thus, when you replace T with double* in your template instantiation, what you get as the return type of the base class's call operator is double* const.

This is different from the return type you have in the derived class's call operator (i.e. const double*, which is equivalent to double const*). In the superclass, you return a constant pointer to a double. On the subclass, you return a non-constant pointer to a constant double.

One way to fix your application is this:

template<typename T>
class DefaultValueFunctorBase
{
    public:
        // Do not return T const here: the top-level const is useless anyway
        virtual T operator() (void) const = 0;
};

// Instantiate your base class template with double const* rather than double*
class DblPtrDft : public DefaultValueFunctorBase<double const*>
{
public:
    DblPtrDft (double default_value_)
    : DefaultValueFunctorBase<double const*>(), // Same change here of course...
    _default_value(default_value_),
    _default_value_ptr(&_default_value)
    {}

    // Return a double const*, consistently with the instantiated template...
    double const* operator() (void) const { return _default_value_ptr; }

private:
    double const*_default_value_ptr;
    double const _default_value;
};

Upvotes: 4

Lily Ballard
Lily Ballard

Reputation: 185663

Your overridden function returns a const double *, but the virtual function, with T = double *, actually has a return type of double * const.

Upvotes: 1

Related Questions