2014-12-18 3 views
23

Ich denke (Gedanken) Ich verstehe auto. Gleiches über decltype. In C++ 14 kann man jedoch einige diabolische Dinge wie decltype(auto) als Rückgabetyp einer Funktion haben. Beachten Sie Folgendes:Warum gibt decltype (auto) hier eine Referenz zurück?

decltype(auto) foo() 
{ 
    int m = 1; 
    return m; 
} 

Der Rückgabetyp ist int, alles Sinn macht. Jedoch

,

decltype(auto) foo() 
{ 
    int m = 1; 
    return (m); 
} 

kehrt int& (d.h. Bezug auf int).

Ich habe absolut keine Ahnung warum das passiert, warum machen diese Klammern überhaupt einen Unterschied !? Hoffe, jemand kann etwas Licht in diese Sache bringen.

PS: Ich habe auch mit C++ getaggt, da es viel mehr Leute gibt, die das C++ Tag als C++14 überprüfen.

+2

Weil 'declltype ((m))' auch eine Lvalue-Referenz ist. – 0x499602D2

+0

Ich dachte schon, also macht das Klammern zu einem Wert? Wenn ich zum Beispiel "(Foo())" zurückgebe, wird angenommen, dass ein Verweis auf "Foo()" zurückgegeben wird. – vsoftco

+1

@vsoftco nein, die Regeln für 'declltype (e)' hängen davon ab, ob 'e' in Klammern gesetzt ist oder nicht. Das bedeutet nicht, dass an anderer Stelle Klammern hinzugefügt werden. –

Antwort

28

7.1.6.2 [dcl.type.simple]

  1. Für einen Ausdruck e, die Art von decltype (e) bezeichnet wird wie folgt definiert:
    - Wenn e ein nicht-entzifferter ID-Ausdruck oder ein nicht-entdeckter Klassenmember-Zugriff (5.2.5) ist, ist declltype (e) der Typ der durch e. Wenn es keine solche Entität gibt, oder wenn ein Satz überladener Funktionen benannt wird, ist das Programm schlecht formatiert.
    - andernfalls, wenn e ein xvalue ist, ist decltype (e) T & &, wobei T der Typ von e ist;
    - andernfalls, wenn e ein Lvalue ist, ist declltype (e) T &, wobei T der Typ von e ist;
    - andernfalls ist decltype (e) der Typ von e.

In Ihrem Beispiel haben Sie return (m) so ist e(m). Das ist kein unparenthesisierter ID-Ausdruck oder Klassenmitgliedszugriff, also gehen wir zum zweiten Punkt. Es ist kein xvalue, also gehen wir zur dritten Kugel. Es ist ein L-Wert, also ist der Typ T&, wobei Tint ist.

+1

spot on, das einzige, was ich nicht verstehe, ist, warum putting '(...)' '' declltype' denkt, dass es einen lval – vsoftco

+4

'm' hat, ist bereits ein lvalue, und' (m) 'ist auch ein lvalue . Der Punkt ist, dass die Klammern ändern, wie "declltype" den Typ ableiten lässt.Ohne die doppelten Klammern erhält man nur den Typ von 'm', mit doppelten Klammern erhält man entweder T && oder T & abhängig davon, ob' m' ein lvalue oder rvalue ist (und in deinem Beispiel ist es ein lvalue) –

+0

Das bekomme ich nicht : erste Zeile in Ihrer Antwort: "wenn e ein ungepressed ... ist" bedeutet "declltype (m)" leitet "int" ab. Die dritte Zeile, wenn e ein Lvalue ist, impliziert "int &". Im ersten Fall ist aber auch "e" (oder "m" in meinem Fall) ein L-Wert, aber weil er keine Klammern hat, wird er als Nicht-Referenz abgeleitet. Ich muss sagen, dass der Standard ein bisschen verwirrend ist, aber ist das was passiert? – vsoftco