其他分享
首页 > 其他分享> > c – Visual Studio 2017是否需要显式移动构造函数声明?

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