如何在std :: map中使用emplace(),其值是std :: set(从某事物映射到集合)?

时间:2015-02-20 16:56:42

标签: c++ c++11 stdmap stdset emplace

问题

我有一个名为std::map<int, std::set<int>>的{​​{1}}。我想知道为什么misimisi.emplace(2345, {6, 9});无法正常工作,如下所示。

代码

misi.emplace({2345, {6, 9}});

以上是#include <set> // std:set #include <map> // std::map #include <utility> // std::piecewise_construct, std::pair #include <tuple> // std::forward_as_tuple #include <iostream> // std::cout, std::endl int main() { // --- std::set initializer list constructor --- std::set<int> si({42, 16}); std::cout << "si.size(): " << si.size() << std::endl; // 2 std::cout << "*si.begin(): " << *si.begin() << std::endl; // 16 // --- std::set emplace() --- si.emplace(7); std::cout << "si.size(): " << si.size() << std::endl; // 3 std::cout << "*si.begin(): " << *si.begin() << std::endl; // 7 std::cout << "--------" << std::endl; ,您可以看到初始化列表构造函数和std::set完美无缺。

emplace()

以上是 // --- std::map initializer list constructor --- std::map<int, int> mii({ {0, 42}, {1, 16} }); std::cout << "mii.size(): " << mii.size() << std::endl; // 2 std::cout << "mii[0]: " << mii[0] << std::endl; // 42 std::cout << "mii[1]: " << mii[1] << std::endl; // 16 // --- std::map emplace() --- mii.emplace(1234, 7); std::cout << "mii.size(): " << mii.size() << std::endl; // 3 std::cout << "mii[1234]: " << mii[1234] << std::endl; // 7 // --- std::map emplace() with std::pair() --- mii.emplace(std::pair<int, int>(2345, 6)); std::cout << "mii.size(): " << mii.size() << std::endl; // 4 std::cout << "mii[2345]: " << mii[2345] << std::endl; // 6 std::cout << "--------" << std::endl; std::map的{​​{1}},您可以看到这些方法也能完美运行,但在上一个示例中,int可能在某种程度上是多余的。我想知道int是否就地构建。 (好吧,我猜不是)

std::pair

对于std::pair // --- std::map to std::set initializer list constructor --- std::map<int, std::set<int>> misi({ {0, {42, 16}}, {1, {7}} }); std::cout << "misi.size(): " << misi.size() << std::endl; // 2 std::cout << "*misi[0].begin(): " << *misi[0].begin() << std::endl; // 16 std::cout << "*misi[1].begin(): " << *misi[1].begin() << std::endl; // 7 ,初始化列表构造函数完美地工作,如上所示。但std::map没有! (如下图所示)

std::set

在这里,以下语法没问题,但并没有完全符合我的要求:

emplace()

所以,似乎没有办法就地创建 // --- Compilation Errors --- //misi.emplace(2345, 6, 9); //misi.emplace({2345, 6, 9}); //misi.emplace(2345, {6, 9}); //misi.emplace({2345, {6, 9}}); //misi.emplace( // std::piecewise_construct, // std::forward_as_tuple(2345), // std::forward_as_tuple(6, 9) //); //misi.emplace( // std::piecewise_construct, // std::forward_as_tuple(2345), // std::forward_as_tuple({6, 9}) //); ,似乎 // --- OK --- misi.emplace(std::pair<int, std::set<int>>(2345, {6, 9})); std::cout << "misi.size(): " << misi.size() << std::endl; // 3 std::cout << "*misi[2345].begin(): " << *misi[2345].begin() << std::endl; //6 std::cout << "--------" << std::endl; return 0; } 是就地创建的(对吗?)。有没有人有任何想法?

我使用的编译器是:

std::pair

1 个答案:

答案 0 :(得分:4)

支持的初始化列表没有类型,因此无法完美转发。在这种特殊情况下,如果您希望构建所有内容,则可以明确指定类型(std::initializer_list<int>):

misi.emplace(
  std::piecewise_construct,
  std::forward_as_tuple(2345),
  std::forward_as_tuple(std::initializer_list<int>{6, 9})
);

由于密钥和值只传递了一个参数,并且initializer_list的{​​{1}}构造函数不是std::set,因此您可以完全删除explicitpiecewise_construct使用带有两个参数的构造函数构造emplace

pair

misi.emplace(
  2345,
  std::initializer_list<int>{6, 9}
);
     

我想知道std :: pair是否就地构建。 (好吧,我   猜不是)

不,构建临时mii.emplace(std::pair<int, int>(2345, 6)); 并传递给std::pair<int, int>emplace构建map value_type的实例({{1} }}) 用它。后者实际存储在pair<const int, int>


map
     

似乎std :: set是就地创建的(对吧?)。

没有。同样,这会创建一个临时misi.emplace(std::pair<int, std::set<int>>(2345, {6, 9})); ,然后使用它构建实际存储在std::pair<int, std::set<int>>map)中的内容。第二种结构将从临时存储的pair<const int, std::set<int>>开始移动。