I'm getting this weird error when inserting an element into std::unordered_map
using emplace
function but not if I use operator[]
function overload. This is my code:
#include <iostream>
#include <unordered_map>
#include <memory>
class B {
public:
B() = default;
~B() = default;
};
class A {
public:
A() = default;
~A() = default;
std::unique_ptr<B> b_ptr;
};
int main() {
std::unordered_map<std::string, A> mp;
// mp.emplace("abc", A()); // gives compiler here
auto& a = mp["def"];
}
I'm getting huge error print when compiled. This is a short note of error: template argument deduction/substitution failed
CodePudding user response:
When you use emplace
like mp.emplace("abc", A());
what you are doing is creating a temporary A
, and that object is then copied/moved into the object that emplace
is going to construct. When you did ~A() = default;
in the class, that gets rid of the compiler supplied default move constructor, and the copy constructor is implicitly deleted because std::unique_ptr
can't be copied so the A()
can't be moved or copied into the object emplace
is going to create.
You can fix this by using the std::piecewise_construct
taged version of emplace to forward the parts of the key value pair to emplace
like
mp.emplace(std::piecewise_construct, // call the piecewise_construct overload
std::forward_as_tuple("abc"), // forwards "abc" to the key
std::forward_as_tuple()); // forwards nothing to the value so it can be default constructed
or you could just add a move constructor to A
using
A(A&&) = default;
so that emplace
can move the A()
you created in main
into mp
.