Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use std::reference_wrapper in std::map

I thought maps and reference_wrappers would go easy but I tripped over something weird:

#include <map>
#include <functional>

int main(void) {
    std::map<int, std::reference_wrapper<const int>> mb;
    const int a = 5;
    mb[0] = std::cref(a);
}

This piece of code gives me the following compiler error:

In file included from c:/MinGW/x86_64-w64-mingw32/include/c++/bits/stl_map.h:63:0,
                 from c:/MinGW/x86_64-w64-mingw32/include/c++/map:61,
                 from ../test/main.cpp:9:
c:/MinGW/x86_64-w64-mingw32/include/c++/tuple: In instantiation of 'std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>) [with _Args1 = {int&&}; long long unsigned int ..._Indexes1 = {0ull}; _Args2 = {}; long long unsigned int ..._Indexes2 = {}; _T1 = const int; _T2 = std::reference_wrapper<const int>]':
c:/MinGW/x86_64-w64-mingw32/include/c++/tuple:1083:63:   required from 'std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>) [with _Args1 = {int&&}; _Args2 = {}; _T1 = const int; _T2 = std::reference_wrapper<const int>]'
c:/MinGW/x86_64-w64-mingw32/include/c++/ext/new_allocator.h:120:4:   required from 'void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const int, std::reference_wrapper<const int> >; _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Tp = std::_Rb_tree_node<std::pair<const int, std::reference_wrapper<const int> > >]'
c:/MinGW/x86_64-w64-mingw32/include/c++/bits/alloc_traits.h:253:4:   required from 'static std::_Require<typename std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::type> std::allocator_traits<_Alloc>::_S_construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::pair<const int, std::reference_wrapper<const int> >; _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Alloc = std::allocator<std::_Rb_tree_node<std::pair<const int, std::reference_wrapper<const int> > > >; std::_Require<typename std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::type> = void]'
c:/MinGW/x86_64-w64-mingw32/include/c++/bits/alloc_traits.h:399:57:   required from 'static decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) std::allocator_traits<_Alloc>::construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::pair<const int, std::reference_wrapper<const int> >; _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Alloc = std::allocator<std::_Rb_tree_node<std::pair<const int, std::reference_wrapper<const int> > > >; decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) = <type error>]'
c:/MinGW/x86_64-w64-mingw32/include/c++/bits/stl_tree.h:423:42:   required from 'std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_create_node(_Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Key = int; _Val = std::pair<const int, std::reference_wrapper<const int> >; _KeyOfValue = std::_Select1st<std::pair<const int, std::reference_wrapper<const int> > >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::reference_wrapper<const int> > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const int, std::reference_wrapper<const int> > >*]'
c:/MinGW/x86_64-w64-mingw32/include/c++/bits/stl_tree.h:1789:64:   required from 'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_emplace_hint_unique(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator, _Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Key = int; _Val = std::pair<const int, std::reference_wrapper<const int> >; _KeyOfValue = std::_Select1st<std::pair<const int, std::reference_wrapper<const int> > >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::reference_wrapper<const int> > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const int, std::reference_wrapper<const int> > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const int, std::reference_wrapper<const int> > >]'
c:/MinGW/x86_64-w64-mingw32/include/c++/bits/stl_map.h:519:8:   required from 'std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](std::map<_Key, _Tp, _Compare, _Alloc>::key_type&&) [with _Key = int; _Tp = std::reference_wrapper<const int>; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::reference_wrapper<const int> > >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = std::reference_wrapper<const int>; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = int]'
../test/main.cpp:20:6:   required from here
c:/MinGW/x86_64-w64-mingw32/include/c++/tuple:1094:70: error: no matching function for call to 'std::reference_wrapper<const int>::reference_wrapper()'
         second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
                                                                      ^
c:/MinGW/x86_64-w64-mingw32/include/c++/tuple:1094:70: note: candidates are:
In file included from ../test/main.cpp:10:0:
c:/MinGW/x86_64-w64-mingw32/include/c++/functional:413:7: note: std::reference_wrapper<_Tp>::reference_wrapper(const std::reference_wrapper<_Tp>&) [with _Tp = const int]
       reference_wrapper(const reference_wrapper<_Tp>& __inref) noexcept
       ^
c:/MinGW/x86_64-w64-mingw32/include/c++/functional:413:7: note:   candidate expects 1 argument, 0 provided
c:/MinGW/x86_64-w64-mingw32/include/c++/functional:407:7: note: std::reference_wrapper<_Tp>::reference_wrapper(_Tp&) [with _Tp = const int]
       reference_wrapper(_Tp& __indata) noexcept
       ^
c:/MinGW/x86_64-w64-mingw32/include/c++/functional:407:7: note:   candidate expects 1 argument, 0 provided

Am I doing something really, really stupid here that I should be aware of? Why isn't this little piece of code working straight forward?

like image 822
WorldSEnder Avatar asked Nov 27 '14 16:11

WorldSEnder


1 Answers

The operator[] of an std::map<K, T> requires that T be default-constructible.

Use this instead:

m.emplace(0, std::cref(a));

In C++17, you can also use one of these:

m.try_emplace(0, std::cref(a));
m.insert_or_assign(0, std::cref(a));
like image 96
Kerrek SB Avatar answered Oct 26 '22 04:10

Kerrek SB