2

Consider the following code (see it on Compiler Explorer):

#include <map>
#include <memory>
#include <vector>
#include <string>

int main()
{
    std::vector<std::map<std::string, std::unique_ptr<int>>> test;
    test.resize(2);
}

It's successfully compiled by GCC 9 and Clang 10, but MSVC 19.24 fails with the following errors:

C:/data/msvc/14.24.28314/include\xmemory(671): error C2280: 'std::pair<const std::string,std::unique_ptr<int,std::default_delete<int>>>::pair(const std::pair<const std::string,std::unique_ptr<int,std::default_delete<int>>> &)': attempting to reference a deleted function
C:/data/msvc/14.24.28314/include\utility(168): note: see declaration of 'std::pair<const std::string,std::unique_ptr<int,std::default_delete<int>>>::pair'
C:/data/msvc/14.24.28314/include\utility(168): note: 'std::pair<const std::string,std::unique_ptr<int,std::default_delete<int>>>::pair(const std::pair<const std::string,std::unique_ptr<int,std::default_delete<int>>> &)': function was implicitly deleted because a data member invokes a deleted or inaccessible function 'std::unique_ptr<int,std::default_delete<int>>::unique_ptr(const std::unique_ptr<int,std::default_delete<int>> &)'
C:/data/msvc/14.24.28314/include\memory(1912): note: 'std::unique_ptr<int,std::default_delete<int>>::unique_ptr(const std::unique_ptr<int,std::default_delete<int>> &)': function was explicitly deleted
C:/data/msvc/14.24.28314/include\xtree(358): note: see reference to function template instantiation 'void std::_Default_allocator_traits<_Alloc>::construct<_Ty,_Ty&>(_Alloc &,_Objty *const ,_Ty &)' being compiled

As I understand the error message, for some reason std::pair<const std::string,std::unique_ptr<int>> needs to be copied. I suppose it's because std::map has to be copied in case of a reallocation.

But why? Doesn't std::map have a move constructor? Is it a bug in MSVC? Or are both GCC and Clang wrong?

cigien
  • 57,834
  • 11
  • 73
  • 112
Ruslan
  • 18,162
  • 8
  • 67
  • 136
  • 1
    Them thing that gets me here is `resize is supposed to [default-insert](https://en.cppreference.com/w/cpp/named_req/DefaultInsertable) the elements into the vector. Looks like MSVC might be making copies instead so that might indeed be a bug. – NathanOliver May 28 '20 at 22:59
  • @NathanOliver It's not limited to default-construction if relocation happens which is a runtime condition. [Here](https://stackoverflow.com/q/53527682/3953764) is an exact duplicate, but I'm not sure if I was correct. – Piotr Skotnicki May 28 '20 at 23:06
  • @PiotrSkotnicki looks pretty good to me (in summary, the `std::map` is not required by the standard to be nothrow-movable, and if the library implementation does not go beyond this minimum spec, the vector.resize must cater to fallback to copy-construction) – M.M May 28 '20 at 23:28

0 Answers0