关于std::map的小坑

Posted on 2018-09-09 17:56:37

我们知道C++11中对 stl 大部分容器添加了函数emplace,能够进行 in place 的构造从而避免不必要的临时变量

struct Foo {
    Foo(int n, float m);
};

std::vector<Foo> v;
v.emplace_back(42, 3.1416);        // 没有临时变量产生
v.push_back(Foo(42, 3.1416));    // 需要产生一个临时变量进行移动构造
v.push_back({42, 3.1416});       // 同上

然而对于map而言,参数被发送给

template< class... Args >
std::pair<iterator,bool> emplace( Args&&... args );

变长参数无法区分key、value,而使用initializer_list也无法推断任何类型。

因而,可以使用tuple以区分key、value

#include <map>
#include <tuple>

int main()
{
    // Create an alias for a tuple of three ints
    using ThreeTuple=std::tuple<int,int,int>;
    // Create an alias for a map of tuple to tuple (of three ints)
    using MapThreeTupleToThreeTuple=std::map<ThreeTuple,ThreeTuple>;

    MapThreeTupleToThreeTuple m;

    // The following does NOT compile
    m.emplace({1,2,3},{4,5,6});

    // The following does NOT compile
    m.emplace(std::piecewise_construct,{1,2,3},{4,5,6});  

    m.emplace(std::forward_as_tuple(1,2,3), std::forward_as_tuple(4,5,6));
    m.emplace(std::make_tuple(1,2,3),  std::make_tuple(4,5,6));
    }

这样固然避免了临时变量,但是写起来略蛋疼我选择insert


还有一个从前一直没注意的问题,std::map::operator[]要求

key_type must meet the requirements of CopyConstructible.
mapped_type must meet the requirements of CopyConstructible and DefaultConstructible.
=default就好了

今天掉坑里了=。=