【问题标题】:CRTP with base class trying to get the return type of a derived class member: invalid use of incomplete type具有基类的 CRTP 试图获取派生类成员的返回类型:不完整类型的无效使用
【发布时间】:2013-07-17 03:21:06
【问题描述】:

考虑以下代码(仅用于示例目的):

#include <iostream>
#include <type_traits>
#include <array>

template <
class Crtp, 
class Vector = typename std::decay<decltype(std::declval<Crtp>().data())>::type, 
class Scalar = typename std::decay<decltype(std::declval<Crtp>().data(0))>::type
>
struct Base
{;};

template <
class Vector = std::array<double, 3>, 
class Scalar = typename std::decay<decltype(std::declval<Vector>()[0])>::type
>
struct Derived
: public Base<Derived<Vector, Scalar>>
{
    Vector _data;
    inline Vector& data() {return _data;}
    inline const Vector& data() const {return _data;}
    inline Scalar& data(const unsigned int i) {return _data[i];}
    inline const Scalar& data(const unsigned int i) const {return _data[i];}
};

int main()
{
    Derived<> d;
    return 0;
}

它返回以下错误:

main.cpp: In instantiation of 'struct Derived<>':
main.cpp:28:14: required from here
main.cpp:16:8: error: invalid use of incomplete type 'struct Derived<>'
main.cpp:16:8: error: declaration of 'struct Derived<>'

有没有办法解决这个问题(不使用 typedef 只使用模板)?

【问题讨论】:

  • 无关注释:inline 在类定义中是多余的。类定义中的所有成员函数定义 (9.3/2) 和友元函数定义 (11.3/7) 都隐含为 inline
  • 是的,我知道这只是一个不幸的复制/粘贴。但是,无论如何,好话。

标签: c++ templates c++11 crtp incomplete-type


【解决方案1】:

这很混乱,因为当 Base 发生模板参数推导时,Derived 并不完整。我认为显而易见的答案 - 明确传递 VectorScalar - 并不令人满意。怎么样:

template <template <class, class> class Derived,
          class Vector, class Scalar>
struct Base {};

template <class Vector, class Scalar>
struct Derived : Base<Derived, Vector, Scalar> {};

为什么不使用typedef 的奇怪限制?我发现:

template <class Vector>
using ScalarTypeOf =
  typename std::decay<decltype(std::declval<Vector>()[0])>::type;

template <class Crtp>
using VectorTypeOf =
  typename std::decay<decltype(std::declval<Crtp>().data())>::type;

template <class Crtp>
struct Base {
  using Vector = VectorTypeOf<Crtp>;
  using Scalar = ScalarTypeOf<Vector>;
};

template <class Vector>
struct Derived : public Base<Derived<Vector>> {
  using Scalar = ScalarTypeOf<Vector>;
};

更具可读性。

【讨论】:

  • 关于 typedef 的限制只是为了检查我是否错过了针对我的真实案例的基于模板的解决方案(这不是提供的示例)。
猜你喜欢
  • 2016-05-27
  • 1970-01-01
  • 1970-01-01
  • 2015-03-30
  • 2019-10-11
  • 1970-01-01
  • 2021-10-25
  • 1970-01-01
相关资源
最近更新 更多