I am experimenting with std::reference_wrapper
. I don't understand why the following does work with a std::vector
but not for a std::unordered_map
:
#include <functional>
#include <vector>
#include <unordered_map>
using namespace std;
int main()
{
vector<vector<long>> x;
vector<reference_wrapper<vector<vector<long>>>> y;
y.push_back(ref(x)); // OK
unordered_map<string, reference_wrapper<vector<vector<long>>>> m;
m["lol"] = ref(x); // NOT OK
}
This is the compilation error I get
/usr/include/c++/7.2.0/tuple:1652:70: error: no matching function for call to ‘std::
reference_wrapper<std::vector<std::vector<long int> > >::reference_wrapper()’
second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
^
In file included from /usr/include/c++/7.2.0/bits/std_function.h:44:0,
from /usr/include/c++/7.2.0/functional:58,
from test.cpp:1:
/usr/include/c++/7.2.0/bits/refwrap.h:325:7: note: candidate: constexpr std::referen
ce_wrapper<_Tp>::reference_wrapper(const std::reference_wrapper<_Tp>&) [with _Tp = s
td::vector<std::vector<long int> >]
reference_wrapper(const reference_wrapper&) = default;
^~~~~~~~~~~~~~~~~
/usr/include/c++/7.2.0/bits/refwrap.h:325:7: note: candidate expects 1 argument, 0
provided
/usr/include/c++/7.2.0/bits/refwrap.h:319:7: note: candidate: std::reference_wrapper
<_Tp>::reference_wrapper(_Tp&) [with _Tp = std::vector<std::vector<long int> >]
reference_wrapper(_Tp& __indata) noexcept
^~~~~~~~~~~~~~~~~
/usr/include/c++/7.2.0/bits/refwrap.h:319:7: note: candidate expects 1 argument, 0
provided
Can someone explain what I am doing wrong?
m["lol"]
uses the unordered maps operator[]
. That operator returns a reference to the item in the map. Which is problematic if there is no such item.
To resolve that, it will default construct the item it's supposed to return. And here lies the problem, because std::reference_wrapper
is not default constructible.
To make the two examples more equivalent, you'd need to use std::unordered_map::insert
or std::unordered_map::emplace
.