template <class P>
pair<iterator, bool> insert(P&& obj); // (1)
Effects: Equivalent to: return emplace(std::forward<P>(obj));
Remarks: This signature shall not participate in overload resolution unless std::is_constructible_v<value_type, P&&> is true.
Also note the other two overloads of insert:
pair<iterator, bool> insert(const value_type& obj); // (2)
pair<iterator, bool> insert(value_type&& obj); // (3)
And the semantics of emplace:
I couldn't find the requirement in the standard but in all implementations emplace constructs a value_type from the args and then attempts to insert it into the container. That is, if emplace is called with a resource handle by rvalue, there will be no resource leak, irrespective of if the emplace resulted in an insertion or not.
To illustrate the DR, consider the following benchmarks:
using M = std::unordered_map<int, int>;
void BM_Fast(int iters) {
M m;
const M::value_type p = {};
while (iters--) m.insert(p);
}
void BM_Slow(int iters) {
M m;
M::value_type p = {}; // not const
while (iters--) m.insert(p);
}
Both implementations I have tried follow the standard and exhibit a big difference in performance; ~10x between BM_Fast and BM_Slow.
The reason is because given a const value_type&, overload (2) is picked and given a value_type&, overload (1) is picked. As noted above emplace() has very different performance characteristics compared to insert().
Remarks: This signature shall not participate in overload resolution unless unless std::is_same_v<value_type, std::decay<P>> is false.