嵌套 std::containers 个可移动对象
Nesting std::containers of movable objects
我有一个 class NoCopy
可移动,但 不可复制。
我需要制作一个 3 个 NoCopy
队列的向量。我可以创建一个空的,但是没有办法添加任何元素。
我可以制作一个 std::vector<NoCopy>
或 std::queue<NoCopy>
并填充它们。但不适用于 std::vector<std::queue<NoCopy>>
.
MWE:
#include <iostream>
#include <vector>
#include <queue>
class NoCopy{
public:
NoCopy() = default;
NoCopy& operator = (const NoCopy&) = delete;
NoCopy(const NoCopy&) = delete;
NoCopy(NoCopy&&) = default;
NoCopy& operator = (NoCopy&&) = default;
};
using QNC = std::queue<NoCopy>;
int main(void) {
QNC q;
q.push(std::move(NoCopy()));
std::vector<NoCopy> ncvec;
ncvec.emplace_back();
std::cout << "Queue size " << q.size() << ", vector size: " << ncvec.size() << std::endl;
std::vector<QNC> qvec;
//????
return 0;
}
有什么想法吗?
默认情况下,std::queue
基于std::deque
,不保证nothrow-movable。另一个合适的标准容器也不是,std::list
;这些规则允许始终分配至少一个 node/block 的实现。 std::vector
在移动可能抛出异常时使用副本重新分配(以保证异常安全)除非类型根本不可复制,并且这两个容器也不会传播 不可复制性 从他们的元素类型,但如果你尝试就会失败。最后一个可以说是标准中的一个缺陷,因为对这种传播的期望不断上升,但修复它与对 incomplete 类型的支持不兼容:
struct Node {
std::vector<Node> children;
// …
};
请注意,libstdc++ 和 libc++ do 都使这两个容器不可移动(从版本 9 开始),这是允许的扩展,但 MSVC 的 STL 不.
您仍然可以使用std::vector<QNC> v(3);
;构造函数“知道”永远不需要 reallocation。或者您可以提供不可复制的 wrapper( 例如 ,从 std::queue
派生的 class)不可移动;前者将放弃 std::vector
的异常安全,而后者将调用 std::terminate
如果移动底层容器 确实 throw.
我有一个 class NoCopy
可移动,但 不可复制。
我需要制作一个 3 个 NoCopy
队列的向量。我可以创建一个空的,但是没有办法添加任何元素。
我可以制作一个 std::vector<NoCopy>
或 std::queue<NoCopy>
并填充它们。但不适用于 std::vector<std::queue<NoCopy>>
.
MWE:
#include <iostream>
#include <vector>
#include <queue>
class NoCopy{
public:
NoCopy() = default;
NoCopy& operator = (const NoCopy&) = delete;
NoCopy(const NoCopy&) = delete;
NoCopy(NoCopy&&) = default;
NoCopy& operator = (NoCopy&&) = default;
};
using QNC = std::queue<NoCopy>;
int main(void) {
QNC q;
q.push(std::move(NoCopy()));
std::vector<NoCopy> ncvec;
ncvec.emplace_back();
std::cout << "Queue size " << q.size() << ", vector size: " << ncvec.size() << std::endl;
std::vector<QNC> qvec;
//????
return 0;
}
有什么想法吗?
默认情况下,std::queue
基于std::deque
,不保证nothrow-movable。另一个合适的标准容器也不是,std::list
;这些规则允许始终分配至少一个 node/block 的实现。 std::vector
在移动可能抛出异常时使用副本重新分配(以保证异常安全)除非类型根本不可复制,并且这两个容器也不会传播 不可复制性 从他们的元素类型,但如果你尝试就会失败。最后一个可以说是标准中的一个缺陷,因为对这种传播的期望不断上升,但修复它与对 incomplete 类型的支持不兼容:
struct Node {
std::vector<Node> children;
// …
};
请注意,libstdc++ 和 libc++ do 都使这两个容器不可移动(从版本 9 开始),这是允许的扩展,但 MSVC 的 STL 不.
您仍然可以使用std::vector<QNC> v(3);
;构造函数“知道”永远不需要 reallocation。或者您可以提供不可复制的 wrapper( 例如 ,从 std::queue
派生的 class)不可移动;前者将放弃 std::vector
的异常安全,而后者将调用 std::terminate
如果移动底层容器 确实 throw.