If I'm constructing a non-trivial container like a custom map for example,
and want to share code between the emplace and insert functions, one approach would be to have the insert function simply call emplace with the supplied element as the argument.
eg.:
template<typename... args>
iterator emplace(int id, args &&... params)
{
// Do complex stuff here, get a location
*location = value_type(std::forward<args>(params) ...);
}
iterator insert(int id, const value_type &element)
{
emplace(id, element);
}
Which in the case of insert & should simply call the copy constructor if I understand correctly?
However in the case of insert && it becomes a little more confusing:
iterator insert(int id, value_type &&element)
{
emplace(id, std::move(element));
}
std::move casts element to an xvalue, which is fine - but will std::forward handle this appropriately? ie. for a non-trivial value_type with a non-default move constructor, will the emplace construction line above correctly call the move constructor?
Yes, you're giving
std::forwarda const lvalue in this scenario, andstd::forwardyields a const lvalue. With that, the copy constructor is called.Yes.
std::forwardturns rvalues into xvalues and lvalues into lvalues. As long as you don't hand it an lvalue, it won't give you an lvalue. This subsequently means that the move constructor will be called, as intended.In
args &&... params,argsdeduces tovalue_type, makingparamsan rvalue reference when the function template is instantiated. The first overload ofstd::forwardis called, andstd::forward<args>(params)yields an xvalue.It's actually quite common to implement
push_backorinsertfor containers in terms ofemplace_backoremplace.