Emplacing a std::pair
Is there a way of emplacing a std::pair?
The arguments need to be suitable for a constructor of pair<int, pair<string,string>>
, the map's value_type
:
my_map.emplace(1, std::make_pair("foo", "bar"));
But doesn't this require unnecessary copying/moving?
No; make_pair
makes a pair of pointers to the string literals, which are then used to initialise (in the case of emplace
) or assigned to (in the case of []
) the strings contained in the map.
In this case there is little point in emplacing the parts of the "value-type" std::pair
, as std::string
can both be efficiently converted from a C-string, and can be efficiently moved into the map. Simple m.emplace( 3, std::make_pair( "bob", "alice" ) )
and you are 99% of the way to optimal efficiency.
However, if you have a std::map
that maps to a type that cannot be efficiently constructed that way, C++11 provides std::piecewise_construct
for std::pair
to be emplace
d.
struct A { }; // nothing
struct C { C(C&&)=delete; }; // no copy/move
struct B { B()=delete; B(B&&)=delete; B(C&&, C&&) {}; }; // no copy/move, only annoying ctor
std::map< int, std::pair<A,B> > test;
// test.emplace( 0, std::make_pair( A{}, B{} ); // does not compile
// test.emplace( 0, std::make_pair( A{}, B{C{},C{}} ); // does not compile
test.emplace( std::piecewise_construct,
std::make_tuple(0),
std::forward_as_tuple(
std::piecewise_construct,
std::forward_as_tuple(A{}),
std::forward_as_tuple( C{}, C{} )
)
); // compiles!
live example
This is an extreme corner case, as efficient-move objects are far more common.