How can I add a (statically defined) unordered_set to an unordered_map, without having to copy the unordered_set?
I tried this:
std::unordered_map<int, std::unordered_set<std::string>> my_map;
for (int i=0; i<100; i++)
my_map.emplace(i, {"foo", "bar"});
and this:
std::unordered_map<int, std::unordered_set<std::string>> my_map;
for (int i=0; i<100; i++)
my_map.insert(i, std::move(std::unordered_set<std::string>({"foo", "bar"})));
but none of them compiles, I get these errors (respectively):
error: no matching function for call to ‘std::unordered_map<int, std::unordered_set<std::basic_string<char> > >::emplace(int&, <brace-enclosed initializer list>)’
and
error: no matching function for call to ‘std::unordered_map<int, std::unordered_set<std::basic_string<char> > >::insert(int&, std::remove_reference<std::unordered_set<std::basic_string<char> > >::type)’
Braced initializers are one of the edge cases that perfect forwarding is not so perfect about.
The issue is that braced initializers passed to function template parameters are in a non-deduced context and compilers are not allowed to deduce a type for them.
Luckily, the fix is pretty easy: just be explicit about the use of
std::initializer_list
.The usual way to solve this issue is by doing something like:
But this doesn't work for
std::string
s becausedecltype(list)
is deduced asstd::initializer_list<const char*>
.