Wie wird der Typ vom automatischen Rückgabetyp abgeleitet?

8

Diese Antwort enthält ein Code-Snippet wie folgt:

%Vor%

Es ist wirklich kompiliert und funktioniert ( zumindest auf Ideone ).

Also, wie wird der Typ in diesem Fall abgeleitet?

Ist die nächste Zeile wirklich nach C ++ 11 Standard erlaubt?

%Vor%

Ich warf einen kurzen Blick darauf, und es sieht nicht gültig aus. Ist das in diesem Fall falsch?

Alle Beispiele im c ++ 11 Standard sind so, dass sie alle nur einen Typ im declltype haben:

%Vor%

ein anderes Beispiel:

%Vor%

und ein anderes

%Vor%

Sie haben alle nur einen Parameter in decltype. Wie kommt es, dass der Top-Code zwei Parameter (getrennt durch ein Komma) enthält?

Ich habe ein anderes Beispiel erstellt (das nicht kompiliert werden kann):

%Vor%

Selbst wenn die Zeile f(v,ops); entfernt wird, wird der Rückgabetyp der Template-Funktion f auf void ausgewertet.

    
BЈовић 02.08.2012, 10:29
quelle

2 Antworten

14

decltype( bool( fun(v[0] ) ), void() ) verwendet den Kommaoperator .

Brechen Sie es auf,

%Vor%

besteht aus zwei Ausdrücken; der erste

%Vor%

wird ausgewertet 1 und verworfen, was dem gesamten Ausdruck den Wert

gibt %Vor%

was ein Wert 2 vom Typ void ist.

decltype ergibt dann den Typ des Ausdrucks, der wie oben void ist.

Der Grund für die Verwendung des Kommaoperators besteht darin, sicherzustellen, dass der gesamte Ausdruck nur dann gültig ist, wenn der erste Unterausdruck gültig ist. Dies liegt daran, dass es in SFINAE verwendet wird, um es von der Substitutionsüberlegung auszuschließen, wenn der erste Unterausdruck ungültig ist.

Das funktioniert, weil decltype zwar syntaktisch wie eine Funktion aussieht, aber tatsächlich ein Sprachkonstrukt ist, das (wie sizeof ) für ein einzelnes Argument definiert ist. Es könnte klarer sein, das Komma-Operator-Argument in Klammern zu setzen:

%Vor%

Notizen

  1. Der Ausdruck bool( fun(v[0] ) ) wird nicht tatsächlich ausgewertet, da wir uns in einem nicht evaluierten Kontext befinden ( decltype , ähnlich wie sizeof ). Was hier von Bedeutung ist, ist, dass ausgewertet würde, wenn der Ausdruck als Ganzes ausgewertet würde, so dass der ganze Ausdruck ungültig ist, wenn der Teilausdruck ungültig ist.
  2. void() ist nicht wirklich ein Wert, sondern verhält sich wie ein Wert im Kontext des Kommaoperators und decltype .
ecatmur 02.08.2012, 10:38
quelle
7

decltype liefert den Typ des Ausdrucks zwischen den Klammern, ohne ihn tatsächlich zu bewerten (behalte das für die nächsten Teile im Hinterkopf).

Der Operator , wertet das linke Argument / den Ausdruck aus, wirft das Ergebnis weg, wertet das richtige Argument aus und liefert das Ergebnis. Daher wird der Rückgabetyp void .

Für den bool(fun(v[0])) -Teil ist es ziemlich einfach. bool(f(...)) erstellt ein temporäres Bool aus dem Ergebnis des Aufrufs von f . Wenn der Rückgabetyp von f nicht in bool konvertiert werden kann, wird ein Fehler ausgelöst, der zu SFINAE führt, da er sich in decltype befindet (dies wird "Ausdruck SFINAE" ).

f(v[0]) übergibt den Rückgabewert von v[0] an f vom Typ T& . Wenn f keinen Parameter hat, in den T& konvertiert werden kann, oder mehr / weniger Parameter akzeptiert, löst dies einen Fehler aus und führt wiederum zu SFINAE aus dem gleichen Grund wie oben.

(Das Gleiche würde passieren, wenn std::vector operator[] nicht unterstützt.)

    
Xeo 02.08.2012 10:42
quelle

Tags und Links