Ответ 1
decltype
может возвращать объявленный тип объекта (отсюда и название), но также может использоваться для запроса типа выражения. Однако в последнем случае результирующий тип "скорректирован" в соответствии с категорией значений этого выражения: выражение lvalue приводит к ссылочному типу lvalue, значению x в ссылочном типе rvalue и prvalue только для типа. Мы можем использовать это в наших интересах:
template<typename T>
struct value_category {
// Or can be an integral or enum value
static constexpr auto value = "prvalue";
};
template<typename T>
struct value_category<T&> {
static constexpr auto value = "lvalue";
};
template<typename T>
struct value_category<T&&> {
static constexpr auto value = "xvalue";
};
// Double parens for ensuring we inspect an expression,
// not an entity
#define VALUE_CATEGORY(expr) value_category<decltype((expr))>::value