Мой базовый класс будет выглядеть примерно так (конечно, с конструкторами):
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[]"
Во-первых, векторы различных типов элементов не связаны, независимо от отношений между типами элементов. Во-вторых, g наследует в частном порядке.





Вам придется вернуть 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)
Или с С++ 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;
}
};
std::vector<T> и std::vector<U> не ковариантны, даже если T и U ковариантны. С типами шаблонов каждая специализация представляет собой собственный уникальный тип, не связанный с другим, кроме имени шаблона.
Что вам нужно, так это вектор общего типа, и вы можете получить его с помощью std::function. Если обе функции возвращают std::vector<std::function<double(double)>>, производная функция переопределяет базовую. Затем вы можете заполнить функции в векторе с помощью лямбда-выражения, которое фиксирует this, чтобы у него был объект для вызова функции-члена.
Если вы не можете этого сделать, другим вариантом будет использование std::vector<std::function<double(gbase const*, double)>>, а затем вам нужно будет передать указатель на объект, для которого вы хотите вызвать функцию, плюс параметр.
Не используйте указатели на функции-члены, вектор указателей на функции-члены в
gBase— это нет, такой же, как вектор указателей на функции-членыg. Ознакомьтесь сstd::function, чтобы найти простой способ решения вашей проблемы.