std::list of move-only type: Cannot emplace into std::vector in VC++
std::list of move-only type: Cannot emplace into std::vector in VC++
在 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()));
}
尝试在 VC++ 2019 中构建会出现以下编译错误:
'A::A(const A &)': attempting to reference a deleted function
显然,VC++ 正在尝试为 A
实例化(左值)复制构造函数,它(正确地)不存在,因为我已经明确定义了 [= 的构造函数之一17=].
我认为通过从另一个 list
移动到 vector
就地实例化 list
应该是有效的 - 即 list
class 确实有一个 move constructor,我认为它应该简单地导致新的 list
取得(移出的)list
中元素的所有权,而不需要任何副本。
实际上,使用Wandbox,same code builds and runs without error使用GCC和Clang。
有人可以解释为什么这段代码不能在 VC++ 2019 中编译吗?我是否有误解 - 为什么(左值)复制构造函数在上面的代码中被 VC++ 编译器实例化实际上是否有正当理由?
备注
当 std::move(...)
不存在时,VC++ 中也会出现同样的错误;即此行发生相同的错误:
v.emplace_back(ListOfA());
MSVC 使用 std::list
的复制构造函数,因为它的移动构造函数正在抛出。在重新分配期间,如果移动构造函数抛出,std::vector
无法提供标准要求的强异常保证。
在你的例子中,向量在重新分配之前没有任何元素,因此看起来没有调用复制构造函数,但这并不意味着不需要复制构造函数。
std::list
在 libstdc++ 和 libc++ 中有 noexcept
移动构造函数。这是允许的,但不是标准要求的。
在 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()));
}
尝试在 VC++ 2019 中构建会出现以下编译错误:
'A::A(const A &)': attempting to reference a deleted function
显然,VC++ 正在尝试为 A
实例化(左值)复制构造函数,它(正确地)不存在,因为我已经明确定义了 [= 的构造函数之一17=].
我认为通过从另一个 list
移动到 vector
就地实例化 list
应该是有效的 - 即 list
class 确实有一个 move constructor,我认为它应该简单地导致新的 list
取得(移出的)list
中元素的所有权,而不需要任何副本。
实际上,使用Wandbox,same code builds and runs without error使用GCC和Clang。
有人可以解释为什么这段代码不能在 VC++ 2019 中编译吗?我是否有误解 - 为什么(左值)复制构造函数在上面的代码中被 VC++ 编译器实例化实际上是否有正当理由?
备注
当 std::move(...)
不存在时,VC++ 中也会出现同样的错误;即此行发生相同的错误:
v.emplace_back(ListOfA());
MSVC 使用 std::list
的复制构造函数,因为它的移动构造函数正在抛出。在重新分配期间,如果移动构造函数抛出,std::vector
无法提供标准要求的强异常保证。
在你的例子中,向量在重新分配之前没有任何元素,因此看起来没有调用复制构造函数,但这并不意味着不需要复制构造函数。
std::list
在 libstdc++ 和 libc++ 中有 noexcept
移动构造函数。这是允许的,但不是标准要求的。