嵌套可移动对象的 std::containers

Ond*_*til 5 c++ containers movable

我有一类NoCopy可移动的,但不是可复制的

我需要制作3 个NoCopy. 我可以创建一个空的,但无法添加任何元素。

我可以制作一个std::vector<NoCopy>orstd::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;
}
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

Dav*_*ing 4

默认情况下,std::queue基于std::deque,不保证是no throw-movable。其他合适的标准容器也不是std::list;这些规则允许始终分配至少一个节点/块的实现。 std::vector使用副本在移动时重新分配可能会抛出异常(以保证异常安全),除非类型根本不可复制,并且这两个容器也不会从其元素类型传播不可复制性,但如果您尝试,就会失败。最后一个可以说是标准中的一个缺陷,因为对这种传播的期望不断提高,但修复它与对不完整的支持不兼容类型的支持不兼容:

\n\n
struct Node {\n  std::vector<Node> children;\n  // \xe2\x80\xa6\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

请注意,libstdc++ 和 libc++确实使这两个容器不可抛出移动(每种情况下均从版本 9 开始),这是允许的扩展,但 MSVC\xe2\x80\x99s STL 则不允许。

\n\n

您仍然可以使用std::vector<QNC> v(3);;构造函数 \xe2\x80\x9c 知道 \xe2\x80\x9d不需要重新分配。或者您可以提供一个不可复制或不可抛出移动的包装器例如,派生自的类);std::queue前者将放弃 的异常安全性std::vector,而后者将std::terminate在移动底层容器确实抛出异常时调用。

\n