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.
CodePudding user response:
Did you try explicitly deleting the l-value overload?
template <typename T>
auto f(T &&) {}
template <typename T>
auto f(T &) = delete;
CodePudding user response:
You can use static_assert
if you don't need SFINAE:
template<typename T>
auto f(T&&) {
static_assert(std::is_rvalue_reference_v<T&&>);
}
CodePudding user response:
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&&) {}