我不确定我的问题标题是否最合适,如果我得到足够的建议,我会很乐意将其更改为更清晰的内容。
在一个主题不是这里的 C++ 视频中,我看到了这个定义:
#include <vector>
// before ":" V is forward declared, it's enough for std::vector?
// node in a tree
struct V : std::vector<V> {};
(评论是我自己的)。
我的理解是,这种看似循环的声明是可能的,因为在该base-clause
位置,struct V
已经(向前)声明了。
但这是合法的 C++ 吗?因为我发现类声明对此没有明确说明。
forward declaration
由其自身定义 ( struct V;
,那么您可以声明 astd::vector<V>)
但不能使用完整的类声明语法。
派生类中的写法:
任何类类型(无论是使用类键 class 还是 struct 声明)都可以声明为派生...
(粗体我的)似乎暗示class-key class
or class-key struct
(没有结束;
)已经是完整的声明。是真的吗,标准中是否更明确?
如果是的话,它可能会给我带来有趣设计的机会,所以我想确保它是合法的。
[编辑]一个更明确的例子,没有std::vector
template <typename T>
struct refwrapper {
T* wrapped;
virtual ~refwrapper() = default;
};
template <typename T>
struct plainwrapper {
T wrapped;
virtual ~plainwrapper() = default;
};
// OK? R is declared at the base-clause
struct R : refwrapper<R> {};
// KO P is incomplete at the base-clause
// struct P: plainwrapper<P>
// {};
类名在标识符之后可以立即查找。请参阅[basic.scope.pdecl]/3。
然而,像往常一样,在
}
类定义结束之前,类是不完整的。基类说明符并不像某些所谓的完整类上下文那样例外。使用类型作为基类要求它是完整的。因此
std::vector<V>
将通过用作基类说明符来实例化,其中V
仍然不完整。通常,使用不完整类型作为模板参数实例化标准库模板会导致未定义的行为。
然而,由于 C++17
std::vector
是例外之一:std::vector
只要类型在std::vector
引用特化的任何成员函数之前完成,就允许使用不完整类型作为模板参数进行实例化。所以是的,自 C++17 起就有效,因为它在结束之前
struct V : std::vector<V> {};
不引用任何成员。std::vector<V>
}