精简到最低限度,这是我要编译的代码:
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;
我确定我只是在做些愚蠢的事情,但我似乎无法弄清楚。
答案 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; };
并从D
和C
继承B<C>
class D : public C, public B<C>
{ };
当您将C
用作B
的模板参数时,它是完全定义的,并且也继承自D
。