Ковариация применяется только к указателю / справочнику полиморфных c типов.
, поэтому вам нужно обернуть double
/ vector<double>
в некоторый класс:
struct IWrapper
{
virtual ~IWrapper() = default;
};
struct DoubleWrapper : IWrapper
{
double d = 0.;
};
struct DoubleVecWrapper : IWrapper
{
std::vector<double> v;
};
И затем у вас может быть что-то вроде:
class IValue
{
public:
virtual ~IValue() = default
virtual int size() = 0;
virtual IWrapper& get() = 0;
};
class Scalar : public IValue {
DoubleWrapper data;
public:
explicit Scalar(double d) : data(d) {}
T& get() override { return data; }
int size() override { return 1; }
};
class Vector : public IValue
{
DoubleVecWrapper data;
public:
Vector(const std::vector<T>& v) : data(v) {}
DoubleVecWrapper& get() override { return data; }
int size() override { return data.v.size(); }
T get_element(int index) { return data[index]; }
};
, но без содержательного интерфейса это в основном бесполезно
// No use of Base interface or inheritance, so ok
void foo(Scalar& value)
{
const auto size = value.size();
auto& wrapper = value.get(); // auto& is DoubleWrapper&
wrapper.d = 4.2;
}
// But, with base class, we cannot go really far:
void foo(IValue& value)
{
const auto size = value.size();
auto& wrapper = value.get(); // auto& is IWrapper&
// What to do now? IWrapper can't do anything
}