I'm referring to this:
#include <utility>
template<typename T, typename = std::enable_if_t<std::is_rvalue_reference_v<T&&>>>
auto f(T&&) {}
int main(){
int i{};
f(std::move(i)); // ok
f(int{1}); // ok
f(i); // compile time error, as expected
}
Are there any other, shorter ways to accomplish the same?
For a moment I thought something like this could work
template<typename T>
auto f(decltype(std::declval<T>())&&) {}
but the IDE told me couldn't infer template argument 'T
', and I verified here, in the section Non-deduced contexts, that the expression of a decltype
-specifier is indeed a non-deduced context.
I'm interested also in a c++17 solution, if any exists.
As @HolyBlackCat commented, you can use concepts to simplify the function signature
#include <type_traits>
template<typename T>
requires (!std::is_lvalue_reference_v<T>)
auto f(T&&) {}
Or detect lvalue or rvalue by checking the validity of a lambda expression that accepts an lvalue reference
#include <utility>
template<typename T>
requires (!requires (T&& x) { [](auto&){}(std::forward<T>(x)); })
auto f(T&&) {}