g++ 认为我的 class 声明是 "forward declaration"
g++ thinks my class declaration is a "forward declaration"
精简到最低限度,这是我要编译的代码:
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++
中编译它,它会抱怨:
error: invalid use of incomplete type ‘class D’
std::vector<typename T::I> v;
并添加注释,
note: forward declaration of ‘class D’
class D : public B<D>
如果我尝试 clang++
,我会得到一个不同的错误:
error: no type named 'I' in 'D'
std::vector<typename T::I> v;
我确定我只是在做一些愚蠢的事情,但我似乎无法弄明白。
问题是当你写
class D : public B<D>
当 D
仍然不完整时,您将 class D
作为 B
的模板参数传递。
因此编译器看不到 D::I
因为此时未定义。
g++ 明确地说:"error: invalid use of incomplete type ‘class D’".
clang++ 没有明确说明这一点,但由于这个原因没有找到 I
。
-- 编辑 --
OP 询问
How do you do what I want to do, then?
我看到的唯一解决方案(不幸的是,这不是一个很好的解决方案)是在另一个 class/struct 中定义您在 B
中需要的内容,比如 C
struct C
{ using I = std::string; };
并从 C
和 B<C>
继承 D
class D : public C, public B<C>
{ };
这种方式 C
是完全定义的,当您将它用作 B
的模板参数时,它也继承自 D
。
精简到最低限度,这是我要编译的代码:
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++
中编译它,它会抱怨:
error: invalid use of incomplete type ‘class D’
std::vector<typename T::I> v;
并添加注释,
note: forward declaration of ‘class D’
class D : public B<D>
如果我尝试 clang++
,我会得到一个不同的错误:
error: no type named 'I' in 'D'
std::vector<typename T::I> v;
我确定我只是在做一些愚蠢的事情,但我似乎无法弄明白。
问题是当你写
class D : public B<D>
当 D
仍然不完整时,您将 class D
作为 B
的模板参数传递。
因此编译器看不到 D::I
因为此时未定义。
g++ 明确地说:"error: invalid use of incomplete type ‘class D’".
clang++ 没有明确说明这一点,但由于这个原因没有找到 I
。
-- 编辑 --
OP 询问
How do you do what I want to do, then?
我看到的唯一解决方案(不幸的是,这不是一个很好的解决方案)是在另一个 class/struct 中定义您在 B
中需要的内容,比如 C
struct C
{ using I = std::string; };
并从 C
和 B<C>
D
class D : public C, public B<C>
{ };
这种方式 C
是完全定义的,当您将它用作 B
的模板参数时,它也继承自 D
。