在 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
(作为 gBase
) this
。你可以改为
(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>
不是协变的,即使 T
和 U
是协变的。对于模板类型,每个特化都是它自己的唯一类型,除了模板名称之外与其他类型无关。
你需要的是一个普通类型的向量,你可以使用 std::function
得到它。如果两个函数 return a std::vector<std::function<double(double)>>
那么派生函数将覆盖基函数。然后,您可以使用捕获 this
的 lambda 填充向量中的函数,以便它具有调用成员函数的对象。
如果你不能这样做,另一种选择是使用 std::vector<std::function<double(gbase const*, double)>>
然后你需要传递一个指向你想要调用函数的对象的指针加上参数。
我的基础 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
(作为 gBase
) this
。你可以改为
(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>
不是协变的,即使 T
和 U
是协变的。对于模板类型,每个特化都是它自己的唯一类型,除了模板名称之外与其他类型无关。
你需要的是一个普通类型的向量,你可以使用 std::function
得到它。如果两个函数 return a std::vector<std::function<double(double)>>
那么派生函数将覆盖基函数。然后,您可以使用捕获 this
的 lambda 填充向量中的函数,以便它具有调用成员函数的对象。
如果你不能这样做,另一种选择是使用 std::vector<std::function<double(gbase const*, double)>>
然后你需要传递一个指向你想要调用函数的对象的指针加上参数。