如何使用emplace()在std :: map的值是std :: set(地图从一个集合)? [英] How to use emplace() in a std::map whose value is a std::set (map from something to a set)?

查看:285
本文介绍了如何使用emplace()在std :: map的值是std :: set(地图从一个集合)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 std :: map< int,std :: set< int>> 命名为 misi 。我想知道为什么 misi.emplace(2345,{6,9}); misi.emplace({2345,{6,9} }

I have a std::map<int, std::set<int>> named misi. I'm wondering why misi.emplace(2345, {6, 9}); and misi.emplace({2345, {6, 9}}); don't work as expected, as shown below.

#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()工作完美。

Above is std::set, you can see that the initializer list constructor and emplace() work perfectly.

    // --- 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 of int int ,你可以看到方法工作完美,除了在最后一个例子中, std :: pair 可能有点冗余。我不知道 std :: pair 是否在原地构造。 (我想不是)

Above is std::map of int to int, you can see the methods work perfectly too, except that in the last example, the std::pair might be somehow redundant. I wonder if the std::pair is constructed in-place or not. (Well, I guess not)

    // --- 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()不会! (如下所示)

For a std::map to a std::set, the initializer list constructor works perfectly as shown above. But the emplace() does not! (as shown below)

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

这里,以下语法是好的,但是不能完全按照我想要的方式:

Here, the following syntax is okay, but doesn't do exactly what I wanted:

    // --- 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 就地,似乎 std :: set 是就地创建的(右?)。有人有任何想法吗?

So, it seems that there is no way to create the std::pair in-place, and it seems that the std::set is created in-place (right?). Does anyone have any ideas?

我使用的编译器是:

$ clang++ --version
Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.4.0
Thread model: posix


推荐答案

支持的初始设置列表没有类型,不能完全转发。在这种特殊情况下,如果你想要构建所有东西,你可以明确指定类型( std :: initializer_list< int> ):

Braced initializer lists have no type, so they can't be perfectly forwarded. In this particular case, you can specify the type (std::initializer_list<int>) explicitly if you want everything to be constructed in place:

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

由于只有一个参数传递给键和值,而 initializer_list 构造函数 std :: set 不是 explicit ,可以删除 piecewise_construct 并使用构造函数构造构造两个参数:

Since only one argument each is passed for the key and the value, and the initializer_list constructor of std::set is not explicit, you can remove the piecewise_construct altogether and have emplace construct the pair using the constructor taking two arguments:

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








mii.emplace(std::pair<int, int>(2345, 6));

我不知道std :: pair是否在原地构造。 (Well,I
guess not)

I wonder if the std::pair is constructed in-place or not. (Well, I guess not)

不,临时 std :: pair< int ,int> 被构造并传递到 emplace ,其构造映射它的 value_type (它是 pair< const int,int> )。后者是实际存储在映射中的内容。

No, a temporary std::pair<int, int> is constructed and passed to emplace, which constructs an instance of the map's value_type (which is pair<const int, int>) with it. The latter is what is actually stored in the map.


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

似乎std :: set是在原地创建的>

it seems that the std::set is created in-place (right?).

否。再次,这将创建一个临时 std :: pair< int,std :: set< int>> ,然后构造实际存储在 map (它是 pair< const int,std :: set< int>> )。第二个构造将执行从存储在临时中的 set< int> 的移动。

No. Again, this creates a temporary std::pair<int, std::set<int>>, and then constructs what's actually stored in the map (which is pair<const int, std::set<int>>) with it. This second construction will perform a move from the set<int> stored in the temporary.

这篇关于如何使用emplace()在std :: map的值是std :: set(地图从一个集合)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆