Das Thema wurde diskutiert vor , aber dies ist kein Duplikat.
Wenn jemand nach dem Unterschied zwischen decltype(a)
und fragt , lautet decltype((a))
die übliche Antwort: - a
ist eine Variable, (a)
ist ein Ausdruck. Ich finde diese Antwort unbefriedigend.
Erstens a
ist auch ein Ausdruck. Die Optionen für einen primären Ausdruck umfassen unter anderem:
- ( Ausdruck )
- ID-Ausdruck
Noch wichtiger ist, dass die Formulierung für decltype Klammern sehr, sehr explizit berücksichtigt :
For an expression e, the type denoted by decltype(e) is defined as follows:
(1.1) if e is an unparenthesized id-expression naming a structured binding, ...
(1.2) otherwise, if e is an unparenthesized id-expression naming a non-type template-parameter, ...
(1.3) otherwise, if e is an unparenthesized id-expression or an unparenthesized class member access, ...
(1.4) otherwise, ...
Die Frage bleibt also. Warum werden Klammern anders behandelt? Ist jemand mit technischen Unterlagen oder Ausschussdiskussionen dahinter vertraut? Die explizite Berücksichtigung von Klammern führt zu der Annahme, dass dies kein Versehen ist. Es muss also einen technischen Grund geben, den ich vermisse.
c++
c++11
language-lawyer
decltype
Ofek Shilon
quelle
quelle
(a)
ist ein Ausdruck unda
ist ein Ausdruck und eine Variable".Antworten:
Es ist kein Versehen. Es ist interessant, dass es in Decltype und Auto (Revision 4) (N1705 = 04-0145) eine Aussage gibt:
Aber in Decltype (Revision 6): Vorgeschlagener Wortlaut (N2115 = 06-018) ist eine der Änderungen
Der Wortlaut enthält keine Begründung, aber ich nehme an, dass dies eine Art Erweiterung des Dekltyps unter Verwendung einer etwas anderen Syntax ist, mit anderen Worten, es war beabsichtigt, diese Fälle zu unterscheiden.
Die Verwendung dafür wird in C ++ Draft9.2.8.4 gezeigt:
Was wirklich interessant ist, ist, wie es mit der
return
Aussage funktioniert :Mein Visual Studio 2019 schlägt mir vor, redundante Klammern zu entfernen, aber tatsächlich wird daraus,
decltype((i))
welche Änderungen einen Rückgabewert ergeben,int&
der es zu UB macht, seit der Verweis auf eine lokale Variable zurückgegeben wird.quelle
Klammern werden nicht anders behandelt. Es ist der unparenthesierte ID-Ausdruck, der anders behandelt wird.
Wenn die Klammern vorhanden sind, gelten die regulären Regeln für alle Ausdrücke. Der Typ und die Wertekategorie werden extrahiert und im Typ von codiert
decltype
.Die spezielle Bestimmung ist da, damit wir nützlichen Code leichter schreiben können. Wenn wir
decltype
auf den Namen einer (Mitglieds-) Variablen anwenden , möchten wir normalerweise keinen Typ, der die Eigenschaften der Variablen darstellt, wenn er als Ausdruck behandelt wird. Stattdessen möchten wir nur den Typ, mit dem die Variable deklariert wird, ohne eine Menge Typmerkmale anwenden zu müssen, um darauf zuzugreifen. Und genau dasdecltype
ist angegeben, um uns zu geben.Wenn wir uns um die Eigenschaften der Variablen als Ausdruck kümmern, können wir sie mit einem zusätzlichen Klammerpaar immer noch recht einfach abrufen.
quelle
int
Mitgliedi
vona
,decltype(a.i)
istint
währenddecltype((a.i))
istint&
(vorausgesetzt,a
ist nichtconst
)? Da der Ausdrucka.i
zuweisbar ist?a.i
ist ein nicht konstanter Wert, daher erhalten Sie einen nicht konstanten Werttyp für(a.i)
.&
, xWerte sind&&
und prWerte sind keine Referenztypen.Vor C ++ 11 benötigt die Sprache Tools, um zwei verschiedene Arten von Informationen zu erhalten :
Aufgrund der Art dieser Informationen mussten die Funktionen in der Sprache hinzugefügt werden (dies ist in einer Bibliothek nicht möglich). Das bedeutet neue Schlüsselwörter. Der Standard hätte dafür zwei neue Schlüsselwörter einführen können. Zum Beispiel
exprtype
, um den Typ eines Ausdrucks unddecltype
den Deklarationstyp einer Variablen abzurufen. Das wäre die klare, glückliche Option gewesen.Das Standardkomitee hat sich jedoch stets bemüht, die Einführung neuer Schlüsselwörter in die Sprache zu vermeiden , um den Bruch alten Codes zu minimieren. Abwärtskompatibilität ist eine Kernphilosophie der Sprache.
Mit C ++ 11 haben wir also nur ein Schlüsselwort für zwei verschiedene Dinge verwendet :
decltype
. Die Art und Weise, wie zwischen den beiden Verwendungen unterschieden wird, besteht in derdecltype(id-expression)
unterschiedlichen Behandlung . Es war eine bewusste Entscheidung des Komitees, ein (kleiner) Kompromiss.quelle
export
wurde eingeführt. Wenn Sie könnenexport
(zuvor wurden alle Vorlagen standardmäßig "exportiert"), können Sie Dinge wiedecltype
und habenconstexpr
. Offensichtlich wäre das Hinzufügenregister
in einer anderen Sprache problematisch.