Ich lese The C ++ Programming Language, 4. Ausgabe (von Bjarne Stroustrup ) überargumentabhängige Suche. Hier ist das Zitat (26.3.6, Overaggressive ADL):
Die argumentabhängige Suche (oft als ADL bezeichnet) ist sehr nützlich, um Ausführlichkeit zu vermeiden (14.2.4). Beispielsweise:
#include <iostream> int main() { std::cout << "Hello, world" << endl; // OK because of ADL }
Ohne argumentabhängige Suche
endl
würde der Manipulator nicht gefunden werden. So wie es ist, bemerkt der Compiler, dass das erste Argument<<
einostream
definiertes in iststd
. Daher sucht esendl
instd
und findet es (in<iostream>
).
Und hier ist das Ergebnis des Compilers (C ++ 11-Modus):
prog.cpp: In function ‘int main()’:
prog.cpp:4:36: error: ‘endl’ was not declared in this scope
std::cout << "Hello, world" << endl;
^
Entweder ist dies ein Fehler im Compiler oder im Buch. Was sagt der Standard?
Aktualisieren:
Ich muss ein bisschen klarstellen. Ich weiß, dass die richtige Antwort zu verwenden ist std::endl
. Die Frage betraf den Text im Buch. Wie Lachlan Easton bereits sagte, ist es nicht nur ein Tippfehler. Der ganze Absatz ist (wahrscheinlich) falsch. Ich kann diese Art von Fehler akzeptieren, wenn das Buch von einem anderen (weniger bekannten) Autor stammt, aber ich war (und bin) im Zweifel, weil es von Bjarne geschrieben wurde.
quelle
std::endl
Kein Fehlerstd::
dies in diesem Fall aufgrund von ADL nicht erforderlich ist. Dies kompiliert aber nicht, daher die Frage.Antworten:
Es ist kein Fehler im Compiler. ADL wird verwendet, um Funktionen und keine Argumente nachzuschlagen .
operator<<
ist die Funktion, die durch ADL hier durch Betrachten der Parameterstd::cout
und (was sollte sein) gefunden wirdstd::endl
.quelle
std::endl
tatsächlich (und verwirrend) eine Funktion ist:endl(std::cout << "Hello, world"); // OK because of ADL
Für diejenigen, die sagen, es ist ein Tippfehler, ist es nicht. Entweder hat Bjarne einen Fehler gemacht oder der Compiler hat einen Fehler gemacht. Der Absatz nach dem von OP geposteten lautet
quelle
<iostream>
)" verwenden.Es ist ein Tippfehler im Buch, wie die anderen bereits betont haben. In dem Buch ist jedoch gemeint, dasswir schreiben müsstenohne ADL. Das hat Bjarne mit Ausführlichkeit gemeint.
Ich stehe korrigiert. Wie Lachlan Easton betont, ist es kein Tippfehler, sondern ein Fehler im Buch. Ich habe keinen Zugang zu diesem Buch, deshalb konnte ich diesen Absatz nicht lesen und selbst realisieren. Ich habe Bjarne diesen Fehler gemeldet, damit er ihn korrigieren kann.
Komisch. Das gleiche Beispiel ist auf Wikipedia und
Kein Zweifel, es ist ein Fehler im Buch. Das Beispiel
std::operator<<(std::cout, "Hello, world").operator<<(std::endl);
zeigt jedoch, wie ADL zur Reduzierung der Ausführlichkeit beiträgt.Vielen Dank an gx_ für den Hinweis auf meinen Fehler .
quelle
std::operator<<
geschieht) und schrieb einen ganzen Absatz mit falschen Informationen. Es lässt Sie wirklich glauben, dass sich die ADL-Regeln geändert haben und dass die Compiler jetzt kaputt sind.std::operator<<(std::cout, "Hello, world").operator<<(std::endl);
(siehe Nichtmitgliedoperator<<
und Mitgliedoperator<<
)Der Hinweis befindet sich im Namen "argumentabhängige Suche".
Es ist die Suche nach nicht qualifizierten Funktionsnamen, die abhängig von den Argumenten funktioniert .
Es hat nichts mit Lookup zu tun für Argumenten .
Bjarne hat falsch geschrieben.
quelle
Ich habe das Buch nicht, aber dies scheint ein Fehler im Buch zu sein. Die Tatsache, dass das Namespace-Qualifikationsmerkmal fehlt, hat nichts mit ADL zu tun. Es sollte sein
std::endl
.quelle
std::cout
) falsch verstanden. Er sprach davon, das zu durchsuchenoperator<<
, nichtendl
.Ja, es ist ein Fehler - das Beispiel ist schlecht geformt und sollte nicht kompiliert werden. ADL gilt für nicht qualifizierte Funktionsnamen, die Funktionsaufrufausdrücke einführen.
endl
ist ein ID-Ausdruck, der versucht, nachzuschlagenstd::endl
.endl
führt keinen Funktionsaufrufausdruck ein, sodass für ihn keine argumentabhängige Suche verwendet wird, sondern nur eine nicht qualifizierte Suche, sodass er nichtstd::endl
wie beabsichtigt gefunden wird.Ein einfacheres und korrektes Beispiel wäre:
Zusammenfassend lässt sich sagen, bevor ein Funktionsaufruf (z. B.
f(x,y,z)
) mit einer nicht qualifizierten ID (z. B.f
) nachgeschlagen wird, zunächst die Parameter der Funktion (zx,y,z
) analysiert, um ihren Typ zu bestimmen. Eine Liste der zugeordneten Namespaces wird basierend auf den Typen erstellt (z. B. ist der einschließende Namespace der Typdefinition ein zugeordneter Namespace). Diese Namespaces werden dann zusätzlich nach der Funktion durchsucht.Die Absicht von Bjarnes Beispiel ist es, die ADL der
std::operator<<
Funktion zu demonstrieren und nichtstd::endl
. Dies erfordert ein zusätzliches Verständnis, dass überladene Operatoren tatsächlich Funktionsaufrufausdrücke sind, alsox << y
bedeutetoperator<<(x,y)
undoperator<<
ein nicht qualifizierter Name ist, und daher gilt ADL für ihn. Der Typ der LHS iststd::ostream
alsostd
ein zugeordneter Namespace und wird daherstd::operator<<(ostream&, ...)
gefunden.Der korrigierte Kommentar sollte lauten:
quelle