如何解决转发CRTP派生的类方法的返回类型
我想通过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(); }
...
但毫不奇怪,海湾合作委员会抱怨说这是invalid use of incomplete type '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() {}
};
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。