I want to emplace an object into a std::map
whose constructor does not take any arguments. However, std::map::emplace
seems to require at least one additional argument besides the key. So how can I forward zero arguments to the constructor?

- 37,307
- 8
- 87
- 112

- 1,440
- 1
- 15
- 32
6 Answers
The element type of std::map<K, V>
is actually std::pair<K, V>
, so when you are emplacing into a map, the arguments will be forwarded to the constructor of std::pair
. That's why you can't pass just the key: std::pair<K, V>
can't be constructed from a single argument (unless it's another pair of the same type.) You can pass zero arguments, but then the key will be value-initialized, which is probably not what you want.
In most cases, moving values will be cheap (and keys will be small and copyable) and you should really just do something like this:
M.emplace(k, V{});
where V
is the mapped type. It will be value-initialized and moved into the container. (The move might even be elided; I'm not sure.)
If you can't move, and you really need the V
to be constructed in-place, you have to use the piecewise construction constructor...
M.emplace(std::piecewise_construct, std::make_tuple(k), std::make_tuple());
This causes std::pair
to construct the first element using k
and the second element using zero arguments (value-initialization).

- 111,498
- 10
- 176
- 312
-
Why not `forward_as_tuple` instead of `make_tuple`? – Yakk - Adam Nevraumont Dec 18 '14 at 19:29
-
@Yakk Well, in this case, to save a bit of typing. Obviously there are cases where `forward_as_tuple` is needed. – Brian Bi Dec 18 '14 at 19:31
-
16Note that a simple `M[k];` will have the same effect as that `piecewise_construct` malarkey. – Mike Seymour Dec 19 '14 at 11:52
-
4M[k] returns a reference; sometimes it's useful to get an iterator instead. – Paul Brannan Jun 20 '16 at 16:26
-
1@Yakk For me, only `make_tuple` worked for a nonmovable type. `forward_as-tuple` would also try to move, which was not possible for my class (intentionally). @Brian saved me here. – sebkraemer Mar 14 '18 at 15:30
-
@sebkraemer Unless you wrote your class wrong, a class that isn't movable should fall back on copying if you try to move it. That is why you *don't* `=delete` the move-ctor; copy-ctor (if it exists) satisfies reasonable move-ctor pre and post requisites. – Yakk - Adam Nevraumont Mar 14 '18 at 15:38
-
@Yakk Sorry, I was unprecise, my class was neither copyable nor movable. – sebkraemer Mar 14 '18 at 20:07
-
@sebkraemer Then make tuple won't help, because it creates values, which are then copied. :) If `make_tuple` works for the arguments to construct it, then `forward_as_tuple` almost always would to. – Yakk - Adam Nevraumont Mar 14 '18 at 20:39
-
@Yakk Hm. It must be that `std::piecewise_construct` really forwards to emplace in-place. It's what cppreference says about this tag, too.I verified with `static_assert` that the value-type class is noncopyable and nonmovable. It compiles if `make_tuple` gets a constructor argument or if called without. You write _almost always would_ but my experience was that my case was different, so +1 for @Brian :) – sebkraemer Mar 15 '18 at 10:19
You could explicitly create a pair
and pass that to map::emplace
, or use the piecewise construction constructor of std::pair
.
struct foo {};
std::map<int, foo> m;
m.emplace(std::pair<int, foo>(1, {}));
m.emplace(std::piecewise_construct,
std::forward_as_tuple(2),
std::forward_as_tuple());

- 106,671
- 19
- 240
- 328
I had the same problem when I had to create an std::map
of std::mutex
objects. The issue is that std::mutex
is neither copyable nor movable, so I needed to construct it "in place".
The accepted answer doesn't work for this case (M.emplace(k, V{});
needs V to be movable). And I didn't want to use the complicated and less readable std::piecewise_construct
option (see above in other answers).
My solution is much simpler - just use the operator[]
- it will create the value using its default constructor and return a reference to it. Or it will just find and return a reference to the already existing item without creating a new one.
std::map<std::string, std::mutex> map;
std::mutex& GetMutexForFile(const std::string& filename)
{
return map[filename]; // constructs it inside the map if doesn't exist
}

- 3,375
- 2
- 40
- 46
-
1Not that I'm knocking this answer, but obviously, this won't work if your object doesn't have a default constructor (constructor taking no arguments). In that case, you'd have to use `try_emplace` (C++17 only) or `emplace`, as detailed in other answers. Note also that this answer is cleaner visually, but is slightly slower (only really important if you're doing this a ton), since it (i.e. `operator[]`) has to check for existence of the object, so it can know whether to return what it found or create a new object there first. – Keith M Feb 08 '19 at 17:54
-
4
-
1@DevNull Like I said, I'm not knocking the answer. However, a Google search for simply "std map emplace constructor arguments" turns up this question, so I thought my comment would be helpful for other people like me who need to emplace with >= 2 arguments. After all, if you don't know how to do 0 arguments, you probably don't know how to do >= 2 arguments, either, and vice versa. I didn't. – Keith M Feb 12 '19 at 20:06
In C++17 you can use std::map::try_emplace
, that uses std::piecewise_construct
internally and doesn't look that cumbersome. It also takes a key as the first argument (instead of forwarding everything into std::pair::pair()
like emplace
does).
#include <map>
struct A {
A() = default;
};
int main()
{
std::map<int, A> map;
map.emplace(std::piecewise_construct,
std::forward_as_tuple(10),
std::forward_as_tuple());
// ...vs...
map.try_emplace(10);
}

- 4,731
- 1
- 30
- 46
-
1Yup, `try_emplace()` is pretty much what `emplace()` should have been. – underscore_d Nov 15 '19 at 13:15
#include <iostream>
#include <unordered_map>
using namespace std;
class A
{
public:
A()
{
cout << "A ctor\n";
}
A(int arg)
{
cout << "A ctor2\n";
}
A(const char* arg)
{
cout << "A ctor3\n";
}
A(int j, const char* arg)
{
cout << "A ctor4\n";
}
A(const A& a)
{
cout << "A copy ctor\n";
}
~A()
{
cout << "A dtor\n";
}
};
int main()
{
unordered_map<int, A> map;
map.emplace(std::piecewise_construct, std::forward_as_tuple(2), std::forward_as_tuple(2, "ups"));
}
Prints output
A ctor4
A dtor

- 4,723
- 2
- 50
- 62
Class ToolMap()
{
friend class std::map;
public (std::map)Object ToolMap()
{
return Object;
}
}

- 57
- 1
- 7
-
This is not valid C++ by a long shot and would not stand a chance at answering the question even if it was. – underscore_d Nov 15 '19 at 13:16