让 class 继承模板类型的所有运算符

Having class inherit all operators of template type

我创建了这个 class 这样我就可以得到任何类型的值,每次使用时它要么是固定的要么是重新计算的:

template <typename T>
class DynamicValue {
    private:
    std::variant<T, std::function<T()>> getter;

    public:
    DynamicValue(const T& constant) : getter(constant){};
    template <typename F, typename = std::enable_if_t<std::is_invocable_v<F>>>
    DynamicValue(F&& function) : getter(function) {}
    DynamicValue(const T* pointer) : DynamicValue([pointer]() { return *pointer; }) {}
    DynamicValue(const DynamicValue& value) : getter(value.getter) {}
    ~DynamicValue() {}
    DynamicValue& operator=(const DynamicValue& value) {
        getter = value.getter;
        return *this;
    }
    operator T() {
        return getter.index() == 0 ? std::get<T>(getter) : std::get<std::function<T()>>(getter)();
    }
};

我还编写了以下虚拟结构来展示我的问题:

struct A {
    int b;
};

问题是,理想情况下,我能够将任何 DynamicValue<T> 视为类型 T。因此,如果我要创建一个新值 (DynamicValue<A> a = A{1};),我将能够执行 a.b 并获取由 a 计算的值的属性 b。但是,我收到以下错误:

'class DynamicValue' has no member named 'b'

您可以尝试一个实例 here

我的问题是:有没有办法克服这个问题,或者我必须接受 ((A) a).b 语法?我考虑过重载每个运算符以实现我的目标,但此解决方案不适用于 . 运算符(和其他运算符),它们不可重载,并且可能有其自身的问题。

The problem is, ideally, I'd be able to treat any DynamicValue<T> as if it were of type T. So if I were to create a new value (DynamicValue<A> a = A{1};), I'd be able to do a.b and get the attribute b of the value calculated by a.

这将需要 operator. 重载或委托继承。两者在 C++ 中都不可用。

我会推荐两个模型:operator() 重载或 operator*

重载调用运算符将​​使您的 DynamicValue 看起来像一个函数,无论它包含一个函数还是一个值:

DynamicValue<A> a = A{1};

auto real_a = a();
std::cout << real_a.b;

如果重载取消引用运算符,您的 class 看起来就像一个指向值的指针,无论它是值还是函数:

DynamicValue<A> a = A{1};

auto real_a = *a;
std::cout << real_a.b;

我会小心 operator->,因为如果您的动态值包含函数,它可能会导致性能显着下降。

我会完全避免隐式转换运算符,因为它带有很多警告和陷阱。这是一把很棒的脚枪,必须谨慎使用。