std::vector 前向声明类型
std::vector on forward declared type
以下代码似乎可以在 Clang++ 和 GCC 上正常工作:
#include <vector>
class A {
private:
int i;
std::vector<A> children;
public:
A& add();
};
A& A::add() { children.emplace_back(); return children.back(); }
int main() {
A a;
A& a2 = a.add();
}
当声明数据成员std::vector<A>
时,A
仍然是一个不完整的类型。使用 std::vector<B>
时相同,而 B
仅使用 class B;
向前声明。
它应该与 std::vector
一起使用,因为它只包含指向 A
.
的指针
这是保证有效,还是未定义的行为?
这是 C++14 及更早版本中的未定义行为; well-defined 在 C++17 中(如果是 17)。
[res.on.functions]/p2,项目符号 2.7:
In particular, the effects are undefined in the following cases:
- [...]
- if an incomplete type (3.9) is used as a template argument when instantiating a template component, unless specifically allowed for
that component.
在 C++14 及更早版本中,std::vector
不会 "specifically allow" 这个。所以行为是未定义的。
对于 C++17,在委员会 2015 年 5 月的会议上通过的 N4510 放宽了 vector
、list
和 forward_list
的这条规则。
根据 cppreference.com 的 "Template Parameters" 部分,这可能适用于 C++17 标准(取决于容器的实际使用情况),但不适用于 C++14 及更早版本。可能您正在使用实现这部分 C++17 标准的编译器版本。
以下代码似乎可以在 Clang++ 和 GCC 上正常工作:
#include <vector>
class A {
private:
int i;
std::vector<A> children;
public:
A& add();
};
A& A::add() { children.emplace_back(); return children.back(); }
int main() {
A a;
A& a2 = a.add();
}
当声明数据成员std::vector<A>
时,A
仍然是一个不完整的类型。使用 std::vector<B>
时相同,而 B
仅使用 class B;
向前声明。
它应该与 std::vector
一起使用,因为它只包含指向 A
.
这是保证有效,还是未定义的行为?
这是 C++14 及更早版本中的未定义行为; well-defined 在 C++17 中(如果是 17)。
[res.on.functions]/p2,项目符号 2.7:
In particular, the effects are undefined in the following cases:
- [...]
- if an incomplete type (3.9) is used as a template argument when instantiating a template component, unless specifically allowed for that component.
在 C++14 及更早版本中,std::vector
不会 "specifically allow" 这个。所以行为是未定义的。
对于 C++17,在委员会 2015 年 5 月的会议上通过的 N4510 放宽了 vector
、list
和 forward_list
的这条规则。
根据 cppreference.com 的 "Template Parameters" 部分,这可能适用于 C++17 标准(取决于容器的实际使用情况),但不适用于 C++14 及更早版本。可能您正在使用实现这部分 C++17 标准的编译器版本。