Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to determine programmatically if an expression is prvalue or lvalue or xvalue in C++? [duplicate]

Tags:

c++

c++11

Each expression in C++11 has a value category. One of lvalue, xvalue or prvalue.

Is there a way to write a macro that, given any expression as an argument, will produce a string "lvalue", "xvalue" or "prvalue" as appropriate?

For example:

int main()
{
    int x;

    cout << VALUE_CAT(x) << endl; // prints lvalue
    cout << VALUE_CAT(move(x)) << endl; // prints xvalue
    cout << VALUE_CAT(42) << endl; // prints prvalue
}

How could VALUE_CAT be implemented?

like image 691
Andrew Tomazos Avatar asked Jan 20 '26 19:01

Andrew Tomazos


2 Answers

decltype can return the declared type of an entity (hence the name), but can also be used to query the type of an expression. However, in the latter case the resulting type is 'adjusted' according to the value category of that expression: an lvalue expression results in an lvalue reference type, an xvalue in an rvalue reference type, and a prvalue in just the type. We can use this to our benefit:

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
like image 152
Luc Danton Avatar answered Jan 22 '26 08:01

Luc Danton


#ifndef _TPF_TYPE_NAME_H
#define _TPF_TYPE_NAME_H

template <typename T>
constexpr bool is_lvalue_helper = std::is_lvalue_reference<T>::value;

template <typename T>
constexpr bool is_xvalue_helper = std::is_rvalue_reference<T>::value;

template <typename T>
constexpr bool is_prvalue_helper = !(is_lvalue_helper<T> || is_xvalue_helper<T>);

template <typename T>
constexpr bool is_rvalue_helper = is_xvalue_helper<T> || is_prvalue_helper<T>;

template <typename T>
constexpr bool is_glvalue_helper = is_xvalue_helper<T> || is_lvalue_helper<T>;

#define is_lvalue(type_instance) is_lvalue_helper<decltype((type_instance))>
#define is_xvalue(type_instance) is_xvalue_helper<decltype((type_instance))>
#define is_prvalue(type_instance)is_prvalue_helper<decltype((type_instance))>
#define is_rvalue(type_instance) is_rvalue_helper<decltype((type_instance))>
#define is_glvalue(type_instance)is_glvalue_helper<decltype((type_instance))>

#endif // end of _TPF_TYPE_NAME_H
like image 43
mada Avatar answered Jan 22 '26 08:01

mada



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!