quant
quant

Reputation: 23082

What's the standard way to emplace a map?

The standard seems to be a bit broken on this, so as far as I've found it only leaves us with this "correct" way of emplacing a map with non-unary constructors of Type (from cppreference):

std::map<std::string, std::string> m;
// uses pair's piecewise constructor (overload 6)
m.emplace(std::piecewise_construct,
          std::forward_as_tuple("c"),
          std::forward_as_tuple(10, 'c'));

Since this is butt-ugly, I was wondering if there is a standard, nice way of emplacing map elements that won't require the copy constructor of Type to be called. Current I'm doing this:

m.emplace("c",std::string(10, 'c'));

But that doesn't feel particularly emplacy. Is there a better way?

Upvotes: 3

Views: 975

Answers (2)

galop1n
galop1n

Reputation: 8824

The emplace parameters in std::map<K,T> are forwarded to a std::pair<const K, V> constructor. It means that you are restricted to available ones.

As you will see, there is not much you can do to improve the syntax, the only variadic construct is the one you use in your first code snippet. All others require an already complete K and V.

Upvotes: 1

Danvil
Danvil

Reputation: 23001

What is the problem with m.emplace("c",std::string(10, 'c'));? std::map needs to store a std::pair to hold key and value. The call m.emplace(A,B) looks perfectly reasonable to specify both key (1. argument) and value (2. argument).

It becomes tricky when the construction of key and/or value requires not only one, but several arguments. Then you have to use the piecewise constructor as mentioned in your question. It is in general impossible to use a variadic template function to construct two objects.

Upvotes: 0

Related Questions