g ++认为我的类声明是“转发声明”

时间:2019-06-20 20:08:03

标签: c++ templates variadic-templates crtp

精简到最低限度,这是我要编译的代码:

template<class T>
class B
{
  protected:

    std::vector<typename T::I> v;

  public:

    template<class... Args>
    void add(Args... args )
    {
      this->v.emplace_back(std::forward<Args>(args)...);
    }

    typename T::I get(int i)
    {
      return this->v[i];
    }
};

class D : public B<D>
{
  public:

    typedef std::string I;
};

如果我实例化D并尝试在g++中进行编译,它将抱怨:

  

错误:无效使用了不完整的类型“ D类”

std::vector<typename T::I> v;

并添加注释,

  

注意:“ D类”的前向声明

class D : public B<D>

如果我改用clang++,则会收到另一个错误:

  

错误:“ D”中没有名为“ I”的类型

std::vector<typename T::I> v;

我确定我只是在做些愚蠢的事情,但我似乎无法弄清楚。

1 个答案:

答案 0 :(得分:4)

问题在于,当您写作

class D : public B<D>

D仍不完整时,您将类B传递为D的模板参数。

因此编译器看不到D::I,因为此时尚未定义。

g ++明确地说:“错误:无效使用了不完整的类型'D类'。”

clang ++并未明确地说出这句话,但由于这个原因没有找到I

-编辑-

OP询问

  

那你怎么做我想做的事?

我看到的唯一解决方案(不幸的是,这不是一个很好的解决方案)是在B的另一个类/结构中定义您需要的内容,例如C

struct C
 { using I = std::string; };

并从DC继承B<C>

class D : public C, public B<C>
 { };

当您将C用作B的模板参数时,它是完全定义的,并且也继承自D