EDIT
Я понял, что мой подход делает то же самое, что код, который вы сказали, не работал, только логически инвертированный:
std::is_lvalue_reference<decltype((expr))>::value
Не могли бы вы уточнить, в какой именно ситуации это работает против ваших ожиданий?
<Ч />
Вы можете использовать правила свертывания ссылок следующим образом:
std::is_rvalue_reference<decltype((expr))&&>::value
Если expr
является lvalue некоторого (возможно, константного) типа T
, decltype((expr))
разрешится до T&
, а T& &&
вернется к T&
.
В противном случае, если expr
является значением x некоторого типа T
, decltype((expr))
будет T&&
, а T&& &&
уменьшится до T&&
.
В противном случае expr
будет prvalue некоторого типа T
, decltype((expr))
даст T
, и, таким образом, весь тип будет T&&
.
Примеры:
template <typename T>
struct is_rvalue : std::is_rvalue_reference<T&&>
{};
struct x {};
x a; const x b{};
static_assert(is_rvalue<decltype((x()))>::value, "x() is an rvalue");
static_assert(!is_rvalue<decltype((a))>::value, "a is an lvalue");
static_assert(!is_rvalue<decltype((b))>::value, "b is an lvalue");
static_assert(is_rvalue<decltype((std::move(a))>::value, "std::move(a) is an rvalue");