2013-05-19 5 views
21

Jeder Ausdruck in C++ 11 hat eine Wertkategorie. Einer von Lvalue, xvalue oder prvalue.Empirisch Wertkategorie von C++ 11 Ausdruck bestimmen?

Gibt es eine Möglichkeit, einen Makro zu schreiben, der bei jedem Ausdruck als Argument die Zeichenfolge "lvalue", "xvalue" oder "prvalue" erzeugt?

Zum Beispiel:

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 
} 

Wie kann VALUE_CAT umgesetzt werden?

+0

Etwas in der Form von '#define VALUE_CAT (expr) get_value_description (sizeof SFINAE_test_1 ((expr)), sizeof SFINAE_test_2 ((expr)))' –

+0

Ich habe mir das ausgedacht, aber ich glaube nicht, dass das zweite ein ist glvalue ... http://ideone.com/ARlW3v –

+0

@BenVoigt Ich glaube nicht, dass eine Lösung mit Überladungsauflösung funktionieren kann, weil ein Überladungssatz einen xvalue nicht von einem prvalue unterscheiden kann. Es ist schade, weil es möglich gewesen wäre, ein Makro insgesamt zu vermeiden (z. B. Überladen von "conexpr" -Funktionen). (Eigentlich bin ich wirklich froh, dass das nicht der Fall ist, würde die Überladungsauflösung komplizierter machen als es schon ist!) –

Antwort

38

decltype kann den deklarierten Typ einer Entität (daher der Name) zurückgeben, kann aber auch verwendet werden, um den Typ eines Ausdrucks abzufragen. Im letzteren Fall wird der resultierende Typ jedoch entsprechend der Wertkategorie dieses Ausdrucks 'angepasst': Ein lvalue-Ausdruck führt zu einem lvalue-Referenztyp, einem xvalue in einem rvalue-Referenztyp und einem prvalue nur zum Typ. Wir können dies zu unserem Vorteil nutzen:

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 
+2

Schön. Demo: http://ideone.com/z2RI8s –

+0

+1, wünschte, ich hätte daran gedacht –

+1

Ich erkannte nicht 'decltype'" gemappt "Ausdruck Wert Kategorien (lvalue, xvalue, prvalue) zu Referenztypen (lvalue Verweis auf T, R-Wert Bezug auf T, T). Vielen Dank. –

1

Sie auch Classification Funktion mit der Klirren API könnten versuchen, die Kategorie des Ausdrucks von einem Klirren AST mit dem Ausdruck zurückzukehren. Dies ist natürlich viel komplexer als @ Lucs Lösung, da es die Erzeugung des tatsächlichen AST durch Klängen erfordert.