将 unordered_set 放在 unordered_map 中

emplace unordered_set in unordered_map

如何将(静态定义的)unordered_set 添加到 unordered_map,而不必复制 unordered_set?

我试过这个:

std::unordered_map<int, std::unordered_set<std::string>> my_map;
for (int i=0; i<100; i++)
  my_map.emplace(i, {"foo", "bar"});

还有这个:

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"})));

但其中 none 编译,我得到这些错误(分别):

error: no matching function for call to ‘std::unordered_map<int, std::unordered_set<std::basic_string<char> > >::emplace(int&, <brace-enclosed initializer list>)’

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)’

映射的元素(mapunordered_map)的类型为 using value type = std::pair<key_t, mapped_type>。因此,emplace 不会将其参数传递给 unordered_set<string> 构造函数!

一旦你意识到这一点,解决方案就是 easy:

std::unordered_map<int, std::unordered_set<std::string>> my_map;
for (int i=0; i<100; i++)
    my_map.emplace(i, std::unordered_set<std::string>{"foo", "bar"});

为了在 std::map<Key, Value> 中插入内容,您需要插入 std::pair<Key, Value>

变化:

my_map.insert(i, std::move(std::unordered_set<std::string>({"foo", "bar"})));

进入:

my_map.insert( std::make_pair(i, std::unordered_set<std::string>({"foo", "bar"})));

你应该可以开始了。

大括号初始化器是完美转发不太完美的边缘情况之一。

问题是传递给函数模板参数的大括号初始化器处于非推导上下文中,不允许编译器为它们推导类型。

幸运的是,修复非常简单:只需明确使用 std::initializer_list

my_map.emplace(i, std::initializer_list<std::string>{"foo", "bar"});

解决此问题的通常方法是执行以下操作:

auto list = { "foo", "bar" };
my_map.emplace(i, list);

但这对 std::string 不起作用,因为 decltype(list) 被推断为 std::initializer_list<const char*>

您可以使用以下代码:

for (int i=0; i<100; i++)
  my_map.emplace(i, std::unordered_set<std::string>({"foo","bar"}));

它将无序集合移动到无序映射中。