Reputation: 23082
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
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
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