c – Visual Studio 2017是否需要显式移动构造函数声明?
作者:互联网
下面的代码可以使用Visual Studio 2015成功编译,但使用Visual Studio 2017失败.Visual Studio 2017报告:
error C2280: “std::pair::pair(const std::pair &)”: attempting to reference a deleted function
码
#include <unordered_map>
#include <memory>
struct Node
{
std::unordered_map<int, std::unique_ptr<int>> map_;
// Uncommenting the following two lines will pass Visual Studio 2017 compilation
//Node(Node&& o) = default;
//Node() = default;
};
int main()
{
std::vector<Node> vec;
Node node;
vec.push_back(std::move(node));
return 0;
}
看起来Visual Studio 2017显式需要移动构造函数声明.是什么原因?
解决方法:
让我们看一下std :: vector源代码(我用实际类型替换了指针和_Ty):
void _Umove_if_noexcept1(Node* First, Node* Last, Node* Dest, true_type)
{ // move [First, Last) to raw Dest, using allocator
_Uninitialized_move(First, Last, Dest, this->_Getal());
}
void _Umove_if_noexcept1(Node* First, Node* Last, Node* Dest, false_type)
{ // copy [First, Last) to raw Dest, using allocator
_Uninitialized_copy(First, Last, Dest, this->_Getal());
}
void _Umove_if_noexcept(Node* First, Node* Last, Node* Dest)
{ // move_if_noexcept [First, Last) to raw Dest, using allocator
_Umove_if_noexcept1(First, Last, Dest,
bool_constant<disjunction_v<is_nothrow_move_constructible<Node>, negation<is_copy_constructible<Node>>>>{});
}
如果Node是no-throw move-constructible或者不是可复制构造的,则调用_Uninitialized_move,否则调用_Uninitialized_copy.
问题是如果您没有显式声明移动构造函数,则类型trait std :: is_copy_constructible_v对于Node是正确的.此声明使复制构造函数被删除.
libstdc以类似的方式实现std :: vector,但是有std :: is_nothrow_move_constructible_v< Node>与MSVC相反,它是错误的.因此,使用移动语义,编译器不会尝试生成复制构造函数.
但是如果我们强迫is_nothrow_move_constructible_v变为假
struct Base {
Base() = default;
Base(const Base&) = default;
Base(Base&&) noexcept(false) { }
};
struct Node : Base {
std::unordered_map<int, std::unique_ptr<int>> map;
};
int main() {
std::vector<Node> vec;
vec.reserve(1);
}
发生同样的错误:
/usr/include/c++/7/ext/new_allocator.h:136:4: error: use of deleted function ‘std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int; _T2 = std::unique_ptr<int>]’
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
标签:move-constructor,c,visual-studio-2017 来源: https://codeday.me/bug/20190930/1836273.html