在unordered_map中放置unordered_set

5

如何将一个(静态定义的)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"})));

但是它们都无法编译,我分别得到了以下错误信息:
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)’

这似乎更像是你想要一个unordered_mapunordered_set(这不是你在问题中所说的)。请澄清一下。 - Walter
4个回答

9

花括号初始化器是完美转发并不那么完美的边缘情况之一。

问题在于传递给函数模板参数的花括号初始化器处于无法推断的上下文中,编译器不能为它们推断类型。

幸运的是,解决方法非常简单:明确使用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 *>


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

一旦你意识到这一点,解决方案就轻而易举

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

2
您可以使用以下代码:
for (int i=0; i<100; i++)
  my_map.emplace(i, std::unordered_set<std::string>({"foo","bar"}));

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

不,unordered_map::emplace 接受右值引用并将其转发到容器中。没有复制,只有移动。 - davidhigh

1
为了在 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"})));

并且你应该可以开始了。

临时变量已经是一个右值,所以你从 OP 复制的 std::move 是无意义的。 - eerorika
4
我猜你的意思是使用std::make_pair而不是std::pair - davidhigh
是的,我确实做了。谢谢! - emvee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接