【问题标题】:emplace unordered_set in unordered_map在 unordered_map 中放置 unordered_set
【发布时间】:2015-09-10 07:20:41
【问题描述】:

如何在不复制 unordered_set 的情况下将(静态定义的)unordered_set 添加到 unordered_map?

我试过了:

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_sets 的unordered_map(这不是您在问题中所说的)。请澄清。

标签: c++ c++11 move unordered-map emplace


【解决方案1】:

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

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

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

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

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

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

但这不适用于std::strings,因为decltype(list) 被推断为std::initializer_list&lt;const char*&gt;

【讨论】:

    【解决方案2】:

    地图的元素(mapunordered_map)的类型为 using value type = std::pair&lt;key_t, mapped_type&gt;。因此,emplace 不会将其参数传递给 unordered_set&lt;string&gt; 构造函数!

    一旦意识到这一点,解决方案就是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"});
    

    【讨论】:

      【解决方案3】:

      您可以使用以下代码:

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

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

      【讨论】:

      • 不,unordered_map::emplace 采用右值引用并将其转发到容器中。没有副本,只有一个动作。
      【解决方案4】:

      要在std::map&lt;Key, Value&gt; 中插入内容,您需要插入std::pair&lt;Key, Value&gt;

      变化:

      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 是没有意义的。
      • 我猜你的意思是std::make_pair而不是std::pair
      • 是的,我确实做到了。谢谢!
      猜你喜欢
      • 2017-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-29
      • 2016-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多