This is what a universal reference is for:
template<typename T>
void ThrSafeQueue::push(T && x) {
lock_guard(mutex_);
queue_.push(std::forward<T>(x));
}
The syntax seems misleading. Here &&
does not actually designate an rvalue reference, but a universal reference that will bind to either an lvalue or an rvalue, depending on the template call.
std::forward will, depending on whether its template is an rvalue on an lvalue, either degenerate to std::move
, or a no-op in a case of an lvalue, exactly what you want.
This example will actually attempt to forward anything, and not just an Obj
, to push()
. This is probably ok, but if you would like to restrict the invocation of the template to be used only with Obj
s, the usual tricks involving std::enable_if
and std::is_same
can be employed, if needed.