在 C++ 中使用成员函数向量时,有没有办法实现协变 return 类型?

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

我的基础 class 看起来像(当然有构造函数):

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;
};

我希望可能的实现看起来像这样:

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;
    }
};

我在定义 g_funcs 时哪里出错了?我运行进入这个:

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[]"

你必须return一个std::vector<cdouble (gBase::*)(double)>,因为std::vector<cdouble (gBase::*)(double)>std::vector<cdouble (g::*)(double)>

之间没有关系

另请注意,g[i][alpha](k) 无法调用其中一个函数,因为您没有传递 g(作为 gBasethis。你可以改为

(g.*g[i][alpha])(k)

或使用 C++17

std::invoke(g[i][alpha], g, k);

但听起来您确实想将 this 与向量中的函数捆绑在一起。在那种情况下,你应该

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

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

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

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

A std::vector<T>std::vector<U> 不是协变的,即使 TU 是协变的。对于模板类型,每个特化都是它自己的唯一类型,除了模板名称之外与其他类型无关。

你需要的是一个普通类型的向量,你可以使用 std::function 得到它。如果两个函数 return a std::vector<std::function<double(double)>> 那么派生函数将覆盖基函数。然后,您可以使用捕获 this 的 lambda 填充向量中的函数,以便它具有调用成员函数的对象。

如果你不能这样做,另一种选择是使用 std::vector<std::function<double(gbase const*, double)>> 然后你需要传递一个指向你想要调用函数的对象的指针加上参数。