Does Visual Studio 2017 need an explicit move constructor declaration?

后端 未结 4 1302
南笙
南笙 2020-12-15 08:29

The below code can be compiled successfully using Visual Studio 2015, but it failed using Visual Studio 2017. Visual Studio 2017 reports:

error C2280:

4条回答
  •  青春惊慌失措
    2020-12-15 08:40

    Let's look at the std::vector source code (I replaced pointer and _Ty with actual types):

    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, negation>>>{});
    }
    

    If Node is no-throw move-constructible or is not copy-constructible, _Uninitialized_move is called, otherwise, _Uninitialized_copy is called.

    The problem is that the type trait std::is_copy_constructible_v is true for Node if you do not declare a move constructor explicitly. This declaration makes copy-constructor deleted.

    libstdc++ implements std::vector in a similar way, but there std::is_nothrow_move_constructible_v is true in contrast to MSVC, where it is false. So, move semantics is used and the compiler does not try to generate the copy-constructor.

    But if we force is_nothrow_move_constructible_v to become false

    struct Base {
        Base() = default;
        Base(const Base&) = default;
        Base(Base&&) noexcept(false) { }
    };
    
    struct Node : Base {
        std::unordered_map> map;
    };
    
    int main() {
        std::vector vec;
        vec.reserve(1);
    }
    

    the same error occurs:

    /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]’
      { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    

提交回复
热议问题