Concept Subspace :: sus :: mem :: IsMoveRef

template <class T>
concept IsMoveRef
requires
std::is_rvalue_reference_v<T>
!std::is_const_v<std::remove_reference_t<T>>

A concept that can be used to constrain a universal reference parameter to ensure the caller provides something that was moved from, akin to receiving by value. This avoids inadvertantly moving out of an lvalue in the caller.

Always invoke IsMoveRef with the decltype of the argument being tested to ensure the correct type is tested, such as IsMoveRef<decltype(arg)>.

In the common case, when you want to receive a parameter that will be moved, it should be received by value. However, library implementors sometimes with to receive an rvalue reference. That is a reference to an rvalue which can be moved from. This is unfortunately spelled the same as a universal reference, so it will also bind to an lvalue in the caller, and moving from the reference would move from the caller's lvalue.

To receive an rvalue reference (and not a universal reference), constrain the input universal reference T&& t by the IsMoveRef concept with requires(IsMoveRef<decltype(t)>). When this is satisfied, the input will need to be an rvalue. In this case, sus::move() will always perform a move from an rvalue and will not move out of an lvalue in the caller.

sus::forward<T> can also be used with universal references, but when constructing a value type T it will implicitly copy from const references.