Czytam The C ++ Programming Language, 4th Edition (by Bjarne Stroustrup ) owyszukiwanie zależne od argumentów. Oto cytat (26.3.6, Overaggressive ADL):
Wyszukiwanie zależne od argumentów (często nazywane ADL) jest bardzo przydatne w celu uniknięcia gadatliwości (14.2.4). Na przykład:
#include <iostream> int main() { std::cout << "Hello, world" << endl; // OK because of ADL }
Bez wyszukiwania zależnego od argumentów
endl
manipulator nie zostałby znaleziony. W obecnej sytuacji kompilator zauważa, że pierwszy argument do<<
jestostream
zdefiniowany wstd
. Dlatego szukaendl
wstd
i znajduje to (w<iostream>
).
A oto wynik wygenerowany przez kompilator (tryb C ++ 11):
prog.cpp: In function ‘int main()’:
prog.cpp:4:36: error: ‘endl’ was not declared in this scope
std::cout << "Hello, world" << endl;
^
Albo jest to błąd w kompilatorze, albo w książce. Co mówi norma?
Aktualizacja:
Muszę trochę wyjaśnić. Wiem, że właściwą odpowiedzią jest użycie std::endl
. Pytanie dotyczyło tekstu w książce. Jak już powiedział Lachlan Easton , nie jest to zwykła literówka. Cały akapit jest (prawdopodobnie) błędny. Mogę zaakceptować tego rodzaju błąd, jeśli książka pochodzi od innego (mniej znanego) autora, ale miałem (i nadal mam) wątpliwości, ponieważ została napisana przez Bjarne'a.
źródło
std::endl
bez błędustd::
nie jest to wymagane w tym przypadku ze względu na ADL. Ale to się nie kompiluje, stąd pytanie.Odpowiedzi:
To nie jest błąd w kompilatorze. ADL służy do wyszukiwania funkcji, a nie argumentów .
operator<<
to funkcja znaleziona tutaj przez ADL, patrząc na parametrystd::cout
i (co powinno być)std::endl
.źródło
std::endl
jest on w rzeczywistości (iendl(std::cout << "Hello, world"); // OK because of ADL
Dla tych, którzy mówią, że to literówka, tak nie jest. Albo Bjarne popełnił błąd, albo kompilator pomylił się. Brzmi akapit po opublikowanym przez OP
źródło
<iostream>
)”.Jest to literówka w książce, jak inni już zauważyli. Jednak w książce chodzi o to,że musielibyśmy pisaćstd::operator<<(std::cout, "Hello, world").operator<<(std::endl);
bez ADL. To właśnie miał na myśli Bjarne przez gadatliwość.
Poprawiono mnie. Jak podkreśla Lachlan Easton , nie jest to literówka, ale błąd w książce. Nie mam dostępu do tej książki, dlatego nie mogłem przeczytać tego akapitu i sam tego zrealizować. Zgłosiłem ten błąd Bjarne'owi, aby mógł go poprawić.
Zabawny. Ten sam przykład jest na Wikipedii i
Bez wątpienia to błąd w książce. Niemniej jednak przykład
std::operator<<(std::cout, "Hello, world").operator<<(std::endl);
pokazuje, jak ADL pomaga zredukować gadatliwość.Dziękuję gx_ za wskazanie mojego błędu .
źródło
std::operator<<
dzieje się wyszukiwanie ) i napisał cały akapit z nieprawidłowymi informacjami. To naprawdę sprawia, że wierzysz, że reguły ADL uległy zmianie i że kompilatory są teraz zepsute.std::operator<<(std::cout, "Hello, world").operator<<(std::endl);
(zobacz osoby niebędące członkamioperator<<
i członkamioperator<<
)Wskazówka jest w nazwie "wyszukiwanie zależne od argumentów".
Jest to wyszukiwanie niekwalifikowanych nazw funkcji, które działa w zależności od argumentów .
To nie ma nic wspólnego z odnośnika do argumenty.
Bjarne źle powiedział.
źródło
Nie mam książki, ale wydaje się, że jest to błąd w książce, fakt, że brakuje w niej kwalifikatora przestrzeni nazw, nie ma nic wspólnego z ADL. Tak powinno być
std::endl
.źródło
std::cout
). Mówił o wyszukiwaniuoperator<<
, a nieendl
.Tak, to błąd - przykład jest źle sformułowany i nie powinien się kompilować. ADL ma zastosowanie do niekwalifikowanych nazw funkcji, które wprowadzają wyrażenia wywołania funkcji.
endl
jest wyrażeniem id próbującym wyszukaćstd::endl
.endl
nie wprowadza wyrażenia wywołania funkcji, więc nie jest do niego używane wyszukiwanie zależne od argumentów, używane jest tylko wyszukiwanie niekwalifikowane, więc nie zostanie znalezionestd::endl
zgodnie z przeznaczeniem.Prostszy i poprawny przykład to:
#include <vector> int main() { std::vector<int> x, y; swap(x,y); // calls std::swap due to ADL }
Podsumowując, zanim wywołanie funkcji (np.
f(x,y,z)
) Z niekwalifikowanym identyfikatorem (np.f
) Zostanie wyszukane, najpierw parametry funkcji (np.x,y,z
analizowane są ) W celu określenia ich typu. Lista powiązanych przestrzeni nazw jest tworzona na podstawie typów (na przykład obejmująca przestrzeń nazw definicji typu jest skojarzoną przestrzenią nazw). Te przestrzenie nazw są następnie dodatkowo przeszukiwane pod kątem funkcji.Celem przykładu Bjarne'a jest pokazanie ADL
std::operator<<
funkcji, a niestd::endl
. Wymaga to dodatkowego zrozumienia, że przeciążone operatory są w rzeczywistości wyrażeniami wywołania funkcji, a więcx << y
oznaczaoperator<<(x,y)
ioperator<<
jest nazwą niekwalifikowaną, a zatem ADL ma do niej zastosowanie. Typ LHS jeststd::ostream
więcstd
skojarzoną przestrzenią nazw i dlategostd::operator<<(ostream&, ...)
został znaleziony.Poprawiony komentarz powinien brzmieć:
źródło