2013-05-20 4 views
13

Ich habe endlich begonnen zu lesen auf und ich verstehe nicht, warum Trailing-Return-Typen erforderlich sind.Warum wurde das Hinzufügen von Trailing-Return-Typen in C++ 11 benötigt?

stieß ich auf das folgende Beispiel, das das Problem hervorzuheben verwendet wird:

template<class Lhs, class Rhs> 
    decltype(lhs+rhs) adding_func(const Lhs &lhs, const Rhs &rhs) {return lhs + rhs;} 

Das Beispiel ist illegal, weil decltype(lhs+rhs) nicht funktioniert, da die Identifikatoren lhs und rhs nur gültig, wenn die Parsing-Phase sind .

Ich denke, meine Frage ist über das Timing von decltype Auflösung. Wenn ich mich nicht irre, wird das Schlüsselwort decltype verwendet, um den Typ eines Ausdrucks zur Kompilierzeit zu bestimmen.

Ich sehe keinen Nachteil darin, dass decltype die Auflösung des Typs durchführt, nachdem alle Analyse abgeschlossen ist (was für das obige Beispiel gut funktionieren würde). Ich glaube, das wäre ein einfacher Weg gewesen, das Problem zu lösen ...

Stattdessen wird der C++ 11-Standard bietet Hinter-Return-Typ:

template<class Lhs, class Rhs> 
    auto adding_func(const Lhs &lhs, const Rhs &rhs) -> decltype(lhs+rhs) {return lhs + rhs;} 

Ich habe keinen Zweifel, dass ich fehle etwas, da ich die andere Verwendung von Trailing-Return-Typen nicht sehen kann. Wo ist der Fehler in meiner Argumentation?

Die trailing-return-Typen scheinen mir eine zu komplexe Lösung zu sein, da die Auflösung des Typs decltype nach dem Parsing des gesamten Funktionskörpers genauso gut funktionieren würde.

Antwort

18

Ich kann nicht einen Nachteil mit decltype sehen auszuführen Auflösung Typ, nachdem alle Parsen abgeschlossen ist (die für das obige Beispiel fein funktionieren würde).

Der Nachteil ist, dass es nicht möglich ist, ohne grundlegend die grundlegenden Grundlagen des C++ Analyse- und Verarbeitungsmodells zu ändern.

Um zu tun, was Sie vorschlagen, muss der Compiler decltype Syntax sehen und einige grundlegende lexikalische Analyse des Inhalts der Syntax. Dann wird die Quelldatei weiter analysiert. Irgendwann später (wann?), Beschließt es zu gehen, "Hey, das Zeug, das ich vorher angeschaut habe? Ich werde jetzt die ganze Parsing-Arbeit für sie machen."

Als allgemeine Regel unterstützt C++ das Suchen voraus für die Definition von Symbolen nicht. Die grundlegende Annahme des C++ - Parsing-Frameworks ist, dass, wenn das Symbol nicht deklariert wird, bevor es verwendet wird, es ein Compilerfehler ist.

Klassen können mit Lookahead, aber nur in Bezug auf ihre Mitglieder wegkommen. Dies liegt zum Teil daran, dass es ziemlich klar ist, wenn sich ein ID-Ausdruck auf eine Member-Variable beziehen kann (dh wenn er sich nicht auf eine bereits deklarierte lokale oder globale Variable im Bereich bezieht). Das ist hier nicht der Fall, wo wir nicht sicher sind, worauf genau sich der ID-Ausdruck beziehen könnte.

Darüber hinaus schafft was Sie vorschlagen Unklarheiten.Was bedeutet das:

int lhs; 

template<class Lhs, class Rhs> 
    decltype(lhs+rhs) adding_func(const Lhs &lhs, const Rhs &rhs); 

Sind die decltype Syntax für die globale Variable lhs beziehen, oder die lokalen lhs Funktionsparameter?

Die Art, wie wir es jetzt tun, gibt es eine klare Abgrenzung zwischen diesen beiden:

int lhs; 
float rhs; 

template<class Lhs, class Rhs> 
    decltype(lhs+rhs) adding_func1(const Lhs &lhs, const Rhs &rhs); 
template<class Lhs, class Rhs> 
    auto adding_func2(const Lhs &lhs, const Rhs &rhs) -> decltype(lhs+rhs); 

adding_func1 bezieht sich auf die globalen Variablen. adding_func2 bezieht sich auf den Funktionsparameter.

So können Sie entweder radikal jeden C++ - Compiler auf der Fläche der Erde brechen. Oder Sie können einfach Ihren Rückgabetyp angeben.

Oder Sie können die C++ 14 Ansatz und not bother to state it at all nehmen.

+0

Danke für Ihre hervorragende Antwort, ich sehe die Anwendungen jetzt. Ich wünschte, ich könnte einen zusätzlichen Cookie für die C++ 14 Referenz geben! –

+0

Auf der C++ 14-Sache: ist es endgültig, dass das enthalten sein wird? Es klingt wie eine Welt der Verletzung in Bezug auf Dokumentation ... – MFH

+0

@MFH: Es ist in der [C++ 14 Community Draft] (http://isocpp.org/blog/2013/05/new-paper-n3690-programming- Sprachen-C-Ausschuss-Entwurf). Unvorhersehbare Konsequenzen werden also wahrscheinlich in C++ 14 liegen. Und ja, es könnte etwas schmerzhaft für die Dokumentation sein. Aber wiederum bedeutet das, dass Sie keine unnötige Redundanz haben, wie zB 'declltype', um den Typ abzuleiten, der genau dem Code * in der Funktion * entspricht. –

4

Nun ein offensichtliches Problem ist, dass es Sie zu Schleifen öffnen würde.

typedef decltype(lhs+lhs) foo; 
foo lhs; 
+0

Ja, ich sehe, wie das problematisch wäre. Aber solche Dinge scheinen für mich wie klare Programmierfehler zu sein und könnten durch Kompilierungsfehler behoben werden. –

+5

@MarcClaesen: Aber es ist kein "klarer" Fehler. Um diesen Fehlertyp zu erkennen, müsste der Compiler das Halteproblem lösen, was unmöglich ist. –

+0

Oh mein Gott, kann nicht glauben, dass ich das vermisst habe. Danke @MikeSeymour! –

Verwandte Themen