简体   繁体   English

std :: move-only类型的列表:无法在VC ++中进入std :: vector

[英]std::list of move-only type: Cannot emplace into std::vector in VC++

In VC++ 2019, I cannot emplace_back an (rvalue) list of a move-only type. 在VC ++ 2019中,我不能emplace_back一个只移动类型的(右值) list

#include <vector>
#include <list>

struct A
{
    A(A&&) {}
};

using ListOfA = std::list<A>;

int main()
{
    std::vector<ListOfA> v;

    // Build error in VC++ 2019
    // No error in Clang and GCC C++11 - C++2a
    v.emplace_back(std::move(ListOfA()));
}

Attempting to build in VC++ 2019 gives the following compile error: 尝试在VC ++ 2019中构建时会出现以下编译错误:

'A::A(const A &)': attempting to reference a deleted function

Clearly, VC++ is attempting to instantiate the (lvalue) copy constructor for A , which (correctly) does not exist because I have explicitly defined one of the constructors for A . 显然,VC ++试图实例化(左值)拷贝构造函数的A ,它(正确地)不存在,因为我已经明确定义构造函数的一个A

I would think that it should be valid to instantiate a list in-place in a vector by moving from another list - that is, the list class does have a move constructor which I'd think should simply cause the new list to take ownership over the elements in the (moved-from) list , without requiring any copies. 我认为通过从另一个list移动来在vector就地实例化list应该是有效的 - 也就是说, list类确实有一个移动构造函数 ,我认为这应该只是让新list取得所有权(移动) list的元素,无需任何副本。

In fact, using Wandbox, the same code builds and runs without error using GCC and Clang. 事实上,使用Wandbox,使用GCC和Clang 构建和运行相同的代码时没有错误

Can somebody explain why this code does not compile in VC++ 2019? 有人可以解释为什么这段代码不能在VC ++ 2019中编译? Do I have a misunderstanding - is there in fact a valid reason why the (lvalue) copy constructor is being instantiated by the VC++ compiler in the code above? 我是否有误解 - 实际上是否有正确的理由为什么(左值)复制构造函数在上面的代码中由VC ++编译器实例化?


Note 注意

The same error occurs in VC++ when the std::move(...) is not present; std::move(...)不存在时,VC ++中会出现同样的错误; ie the same error occurs with this line: 即此行发生相同的错误:

v.emplace_back(ListOfA());

MSVC uses the copy constructor of std::list because its move constructor is throwing. MSVC使用std::list的复制构造函数,因为它的移动构造函数正在抛出。 During reallocation, if the move constructor throws, std::vector cannot provide strong exception guarantee as required by the standard. 在重新分配期间,如果移动构造函数抛出,则std::vector无法提供标准所要求的强异常保证。

In your case, the vector does not have any element before reallocation, so it appears that the copy constructor is not called, but that doesn't mean the copy constructor is not needed. 在您的情况下,向量在重新分配之前没有任何元素,因此看起来没有调用复制构造函数,但这并不意味着不需要复制构造函数。

std::list in libstdc++ and libc++ has noexcept move constructor. libstdc ++中的std::list和libc ++有noexcept移动构造函数。 This is permitted but not required by the standard. 这是允许的,但标准不要求。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM