First off, this question is not a duplicate of Function dual to std::move? or of Does the inverse of std::move exist?. I am not asking about a mechanism to
The most simple solution is this one:
template<typename T>
T& force(T&& t){
return t;
}
The function provided below is a bad idea. Don't use it. It provides a very easy path towards dangling references. I'd consider the code that needs it faulty and act accordingly.
Still, I think this is an interesting exercise for some reason, so I can't help but show it.
Inside a function, the names of its arguments are lvalues, even if the arguments are rvalue references. You can use that property to return an argument as an lvalue reference.
template <typename T>
constexpr T& as_lvalue(T&& t) {
return t;
};
This appears to work in all of your cases:
template <class T>
constexpr typename std::remove_reference<T>::type& copy(T&& t) {
return t;
};
It's exactly like std::move
, except it returns an lvalue reference instead.
Leave perfect forwarding out of your forwarding function, and you have no_move
:
template<class T> constexpr T& no_move(T&& x) {return x;}
Just be sure pretending you have an lvalue-reference instead of an rvalue reference is ok, as that circumvents the protection against binding of temporaries to non-const references and such.
Any code using this function is with near-certainty defective-by-design.
In your example use-case, the proper way would be changing the argument-type of f()
to const&
so no such adaptor is neccessary, and using const_cast
to add to the cache of saved computations.
Be sure not to change non-mutable
members on an object declared const
though.