Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Empirically determine value category of C++11 expression?

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 904
Andrew Tomazos Avatar asked May 19 '13 18:05

Andrew Tomazos


People also ask

What are value categories C++?

C++ defines 3 value categories which represent the useful combination of these properties: lvalue (expressions with identity but not movable from), xvalue (expressions with identity that are moveable from), and prvalue (expressions without identity that are moveable from).

What are value categories?

Walter Goodnow Everett classified values into the following eight categories; (1) economic values, (2) bodily values, (3) value of recreation, (4) value of association, (5) character values, (6) aesthetic values, (7) intellectual values, (8) religious values.

What is rvalue in C++ 11?

Prerequisites: lvalue and rvalue in C++, References in C++ “l-value” refers to a memory location that identifies an object. “r-value” refers to the data value that is stored at some address in memory.

What are Lvalues and Rvalues?

An lvalue refers to an object that persists beyond a single expression. An rvalue is a temporary value that does not persist beyond the expression that uses it.


1 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 61
Luc Danton Avatar answered Sep 23 '22 02:09

Luc Danton