How to omit perfect forwarding for deduced parameter type?

SFINAE hidden in a template parameter list:

#include <type_traits>

template <typename T
        , typename = typename std::enable_if<!std::is_lvalue_reference<T>{}>::type>
void f(T&& v);

template <typename T>
void f(const T& v);

DEMO


SFINAE hidden in a return type:

template <typename T>
auto f(T&& v)
    -> typename std::enable_if<!std::is_lvalue_reference<T>{}>::type;

template <typename T>
void f(const T& v);

DEMO 2


In c++14 typename std::enable_if<!std::is_lvalue_reference<T>{}>::type can be shortened to:

std::enable_if_t<!std::is_lvalue_reference<T>{}> 

Anyway, even in c++11 you can shorten the syntax with an alias template if you find it more concise:

template <typename T>
using check_rvalue = typename std::enable_if<!std::is_lvalue_reference<T>{}>::type;

DEMO 3


With c++17 constexpr-if:

template <typename T>
void f(T&& v)
{
    if constexpr (std::is_lvalue_reference_v<T>) {}
    else {}
}

With c++20 concepts:

template <typename T>
concept rvalue = !std::is_lvalue_reference_v<T>;

void f(rvalue auto&& v);

void f(const auto& v);

DEMO 4


How about a second level of implementation:

#include <utility>
#include <type_traits>

// For when f is called with an rvalue.
template <typename T>
void f_impl(T && t, std::false_type) { /* ... */ }

// For when f is called with an lvalue.
template <typename T>
void f_impl(T & t, std::true_type) { /* ... */ }

template <typename T>
void f(T && t)
{
    f_impl(std::forward<T>(t), std::is_reference<T>());
}

I think SFINAE should help:

template<typename T,
         typename = typename std::enable_if<!std::is_lvalue_reference<T>::value>::type>
void f (T &&v) // thought to be rvalue version
{
   // some behavior based on the fact that v is rvalue
   auto p = std::move (v);
   (void) p;
}

template <typename T>
void f (const T &v) // never called
{  
   auto p = v;
   (void) p;
}