Search code examples
c++inheritancevectorstdvectorcovariant-return-types

Is there a way to implement covariant return types when using a vector of member functions in C++?


My base class will look something like (with constructors of course):

class gBase
{
public:
    // The user will implement a vector of a vector of functions that can be called as g[i][alpha](k)
    virtual vector<cdouble (gBase::*)(double)> operator[] (uint i) = 0;
};

and I want a possible implementation to look something like this:

class g : gBase
{
public:
    g() : g_funcs({{g_00, g_01}}) {}
    vector<cdouble (g::*)(double)>  operator[] (uint i)
    {
        return g_funcs[i];
    }
private:
    vector<vector<cdouble (g::*)(double)> > g_funcs;

    // define each function.
    cdouble g_00(double k)
    {
        return 5.0;
    }

    cdouble g_01(double k)
    {
        return 3.0;
    }
};

Where am I going wrong in defining g_funcs? I run into this:

return type is not identical to nor covariant with return type "std::__1::vector<cdouble (gBase::*)(double), std::__1::allocator<cdouble (gBase::*)(double)>>" of overridden virtual function "gBase::operator[]"

Solution

  • A std::vector<T> and std::vector<U> are not covariant even if T and U are covariant. With template types, each specialization is it's own unique type with no relation to the other besides the template name.

    What you need is a vector of a common type, and you can get that using std::function. If both functions return a std::vector<std::function<double(double)>> then the derived function will override the base one. You could then populate the functions in the vector by using a lambda that captures this so it has the object to call the member function on.

    If you can't do that another option would be to use a std::vector<std::function<double(gbase const*, double)>> and then you would need pass a pointer to the object you want to call the function on plus the parameter.