microsoft / microsoft/STL

<vector>: Cannot `resize`/`reserve` an instance of `std::vector<std::unordered_map<int, move_only_type>>`

Open
#5,084 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

LEWG issue needed
Dominant language
C++
Stars
11.1k
Forks
1.7k
Avg merge
4d 15h
Merged PRs (30d)
22

Description

Describe the bug

vector and unordered_map seem to interact in an unexpected way. I can resize a vector of move-only type, I can emplace into an unordered_map of move-only mapped_type, but MS-STL won't allow me to resize a vector of unordered_map of move-only mapped_type.

Command-line test case

PS C:\Users\mate\Desktop> gc .\repro.cpp
#include <unordered_map>
#include <memory>
#include <vector>

int main()
{
    std::unordered_map<int, std::unique_ptr<int>> a;
    a.emplace(0, nullptr); // OK

    std::vector<std::unique_ptr<int>> b;
    b.resize(1); // OK

    std::vector<std::unordered_map<int, std::unique_ptr<int>>> c;
    //c.resize(1); // ERROR
    c.reserve(1); // ERROR

    return (int)(a.size() + b.size() + c.size());
}

PS C:\Users\mate\Desktop> cl /O2 /EHsc /std:c++17 /permissive- /W4 .\repro.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.41.34120 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

repro.cpp
C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.41.34120\include\xmemory(700): error C2280: 'std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>::pair(const std::pair<const int,std::unique_ptr<int,std::default_delete<int>>> &)': attempting to reference a deleted function
C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.41.34120\include\utility(250): note: see declaration of 'std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>::pair'
C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.41.34120\include\utility(250): note: 'std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>::pair(const std::pair<const int,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:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.41.34120\include\memory(3451): 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:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.41.34120\include\xmemory(700): note: the template instantiation context (the oldest one first) is
.\repro.cpp(7): note: see reference to class template instantiation 'std::unordered_map<int,std::unique_ptr<int,std::default_delete<int>>,std::hash<int>,std::equal_to<int>,std::allocator<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>>>' being compiled
C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.41.34120\include\unordered_map(105): note: while compiling class template member function 'std::unordered_map<int,std::unique_ptr<int,std::default_delete<int>>,std::hash<int>,std::equal_to<int>,std::allocator<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>>>::unordered_map(const std::unordered_map<int,std::unique_ptr<int,std::default_delete<int>>,std::hash<int>,std::equal_to<int>,std::allocator<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>>> &)'
C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.41.34120\include\xmemory(700): note: see the first reference to 'std::unordered_map<int,std::unique_ptr<int,std::default_delete<int>>,std::hash<int>,std::equal_to<int>,std::allocator<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>>>::unordered_map' in 'std::_Default_allocator_traits<_Alloc>::construct'
        with
        [
            _Alloc=std::allocator<std::unordered_map<int,std::unique_ptr<int,std::default_delete<int>>,std::hash<int>,std::equal_to<int>,std::allocator<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>>>>
        ]
C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.41.34120\include\xmemory(1779): note: see the first reference to 'std::_Default_allocator_traits<_Alloc>::construct' in 'std::_Uninitialized_backout_al<std::allocator<std::unordered_map<int,std::unique_ptr<int,std::default_delete<int>>,std::hash<int>,std::equal_to<int>,std::allocator<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>>>>>::_Emplace_back'
        with
        [
            _Alloc=std::allocator<std::unordered_map<int,std::unique_ptr<int,std::default_delete<int>>,std::hash<int>,std::equal_to<int>,std::allocator<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>>>>
        ]
C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.41.34120\include\xmemory(1833): note: see the first reference to 'std::_Uninitialized_backout_al<std::allocator<std::unordered_map<int,std::unique_ptr<int,std::default_delete<int>>,std::hash<int>,std::equal_to<int>,std::allocator<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>>>>>::_Emplace_back' in 'std::_Uninitialized_copy'
C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.41.34120\include\unordered_map(106): note: see reference to function template instantiation 'std::_Hash<std::_Umap_traits<_Kty,_Ty,std::_Uhash_compare<_Kty,_Hasher,_Keyeq>,_Alloc,false>>::_Hash<std::allocator<std::_List_node<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>,std::_Default_allocator_traits<_Alloc>::void_pointer>>>(const std::_Hash<std::_Umap_traits<_Kty,_Ty,std::_Uhash_compare<_Kty,_Hasher,_Keyeq>,_Alloc,false>> &,const _Any_alloc &)' being compiled
        with
        [
            _Kty=int,
            _Ty=std::unique_ptr<int,std::default_delete<int>>,
            _Hasher=std::hash<int>,
            _Keyeq=std::equal_to<int>,
            _Alloc=std::allocator<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>>,
            _Any_alloc=std::allocator<std::_List_node<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>,std::_Default_allocator_traits<std::allocator<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>>>::void_pointer>>
        ]
C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.41.34120\include\xhash(388): note: see reference to function template instantiation 'void std::_Hash<std::_Umap_traits<_Kty,_Ty,std::_Uhash_compare<_Kty,_Hasher,_Keyeq>,_Alloc,false>>::_Insert_range_unchecked<std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>>>,std::_Iterator_base0>,std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>>>,std::_Iterator_base0>>(_Iter,const _Sent)' being compiled
        with
        [
            _Kty=int,
            _Ty=std::unique_ptr<int,std::default_delete<int>>,
            _Hasher=std::hash<int>,
            _Keyeq=std::equal_to<int>,
            _Alloc=std::allocator<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>>,
            _Iter=std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>>>,std::_Iterator_base0>,
            _Sent=std::_List_unchecked_const_iterator<std::_List_val<std::_List_simple_types<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>>>,std::_Iterator_base0>
        ]
C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.41.34120\include\xhash(950): note: see reference to function template instantiation 'std::pair<std::_List_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,bool> std::_Hash<std::_Umap_traits<_Kty,std::unique_ptr<int,std::default_delete<int>>,std::_Uhash_compare<_Kty,_Hasher,_Keyeq>,_Alloc,false>>::emplace<const std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>&>(const std::pair<const int,std::unique_ptr<int,std::default_delete<int>>> &)' being compiled
        with
        [
            _Ty=std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>,
            _Kty=int,
            _Hasher=std::hash<int>,
            _Keyeq=std::equal_to<int>,
            _Alloc=std::allocator<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>>
        ]
C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.41.34120\include\xhash(610): note: see reference to function template instantiation 'std::_List_node_emplace_op2<std::allocator<std::_List_node<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>,std::_Default_allocator_traits<_Alloc>::void_pointer>>>::_List_node_emplace_op2<const std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>&>(_Alnode &,const std::pair<const int,std::unique_ptr<int,std::default_delete<int>>> &)' being compiled
        with
        [
            _Alloc=std::allocator<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>>,
            _Alnode=std::allocator<std::_List_node<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>,std::_Default_allocator_traits<std::allocator<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>>>::void_pointer>>
        ]
C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.41.34120\include\list(585): note: see reference to function template instantiation 'void std::_Default_allocator_traits<_Alloc>::construct<_Ty,const std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>&>(_Alloc &,_Objty *const ,const std::pair<const int,std::unique_ptr<int,std::default_delete<int>>> &)' being compiled
        with
        [
            _Alloc=std::allocator<std::_List_node<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>,std::_Default_allocator_traits<std::allocator<std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>>>::void_pointer>>,
            _Ty=std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>,
            _Objty=std::pair<const int,std::unique_ptr<int,std::default_delete<int>>>
        ]

Expected behavior

Have the code compile, like libstdc++ allows this.

Versions

Visual Studio

PS C:\Users\mate\Desktop> Get-CimInstance MSFT_VSInstance -Namespace root/cimv2/vs | `
>> where Caption -match 'Build Tools 2022' | `
>> select -exp Version
17.11.35312.102

MSVC

Microsoft (R) C/C++ Optimizing Compiler Version 19.41.34120 for x64

STL

#define _CPPLIB_VER       650
#define _MSVC_STL_VERSION 143
#define _MSVC_STL_UPDATE  202405L

Additional context

Obligatory Godbolt

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by compiling the provided repro.cpp with the stated MSVC version and compare the failing vector operations with the successful cases. Trace the diagnostic through the mentioned headers, including vector, unordered_map, xmemory, xhash, list, and utility; done means the repro compiles for both resize and reserve with the move-only mapped type.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.