c++ - CRTP 派生类方法的返回类型的转发

标签 c++ c++11 crtp perfect-forwarding static-polymorphism

我想通过 CRTP 使用“静态多态性”来执行如下操作:

template <typename T>
struct Base
{
    double get_value() const { return ((T*)this)->_get_value(); }

protected:
    ~Base() {}
};

struct Derived1 : public Base<Derived1>
{
    double value;

    Derived1() : value(3.) {}

    const double& _get_value() const { return value; }
};

struct Derived2 : public Base<Derived2>
{
    double _get_value() const { return 5.; }
};

这可行,但我也希望在对象实例化为 Derived1 的情况下,get_value 返回对该值的 const 引用,而不是返回复制。所以在某种程度上,这是一种返回值的“完美转发”。

我尝试像这样声明 get_value 的返回类型:

template <typename T>
struct Base
{
    decltype(std::declval<T>()._get_value()) get_value() const { return ((T*)this)->_get_value(); }
    ...

但不出所料,GCC 提示这是对不完整类型“struct Derived1”的无效使用

有什么办法可以解决这个问题吗?

提前谢谢您! :)

最佳答案

GCC 拒绝 OP 中提出的解决方案的原因是 Base<Derived1>正在实例化之前 Derived1 。此实例化由所有成员函数的签名的实例化组成,但它不会实例化函数体本身。

所以我们需要推迟确定成员函数的签名/返回类型,直到之后 Derived1可见。

实现此目的的一种方法是通过 decltype(auto) 推迟返回类型的确定。这使得返回类型依赖于函数体(不会立即实例化)。不幸的是,这是一个 C++14 功能。

template <typename T>
struct Base
{
    decltype(auto) get_value() const { return ((T*)this)->_get_value(); }

protected:
    ~Base() {}
};

参见https://godbolt.org/z/r1T56n


这可能包含在 dcl.spec.auto 中和 temp.inst .


或者,即使在 C++11 中,您也可以通过将函数转换为函数模板来推迟返回类型的确定,如有必要,还可以依赖于某些虚拟参数:

template <typename T>
struct Base
{
    template<typename U=T>
    decltype(std::declval<U>()._get_value()) get_value() const {
        return ((T*)this)->_get_value();
    }

protected:
    ~Base() {}
};

关于c++ - CRTP 派生类方法的返回类型的转发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64368517/

相关文章:

c++ - 使用 CRTP 进行模拟类

c++ - 如何在不改变 X 位置的情况下堆叠矩形?

c++ - 如何设计只移动对象的阻塞队列?

c++ - 为什么 xvalue 不绑定(bind)到非常量左值引用?

c++ - 在 C++ 中如何声明 std::array 的别名?

c++ - 错误 : no member named 'rank_' in 'EndIndex'

c++ - .NET 的 String.IsNullOrWhiteSpace 在 C++ 中的等效项是什么?

c++ - 在 C++ 中,如果成员函数是虚拟的,什么时候可以使用静态绑定(bind)?

C++ 从基类中的非虚函数调用纯虚函数

c++ - 将 CRTP 与 SFINAE 混合