我想通过 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/