Я читаю язык программирования C ++, 4-е издание ( Бьярна Страуструпа ) оаргумент-зависимый поиск. Вот цитата (26.3.6, Сверхагрессивный ADL):
Поиск, зависящий от аргументов (часто называемый ADL), очень полезен, чтобы избежать многословия (14.2.4). Например:
#include <iostream> int main() { std::cout << "Hello, world" << endl; // OK because of ADL }
Без поиска, зависящего от аргументов,
endl
манипулятор не будет найден. Как это, замечает , компилятор , что первый аргумент<<
приведенostream
определенный вstd
. Таким образом, он ищетendl
вstd
и находит его (в<iostream>
).
И вот результат компилятора (режим 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;
^
Либо это ошибка в компиляторе, либо в книге. Что говорит стандарт?
Обновить:
Мне нужно немного уточнить. Я знаю, что правильный ответ - использовать std::endl
. Вопрос был о тексте в книге. Как уже сказал Лахлан Истон , это не просто опечатка. Весь абзац (вероятно) неверен. Я могу согласиться с такой ошибкой, если книга написана другим (менее известным) автором, но я был (и все еще сомневаюсь), потому что она была написана Бьярном.
источник
std::endl
нет ошибкиstd::
в этом случае не требуется из-за ADL. Но это не компилируется, отсюда и вопрос.Ответы:
Это не ошибка компилятора. ADL используется для поиска функций, а не аргументов .
operator<<
- это функция, которую можно найти здесь через ADL, просмотрев параметрыstd::cout
и (что должно быть)std::endl
.источник
std::endl
на самом деле (и сбивает с толку) функцию:endl(std::cout << "Hello, world"); // OK because of ADL
Для тех, кто говорит, что это опечатка, это не так. Либо Бьярн ошибся, либо компилятор ошибся. Абзац после того, что опубликовал OP, гласит
источник
<iostream>
)».Это опечатка в книге, как уже указывали другие. Однако в книге имеется в виду, чтонам придется написатьstd::operator<<(std::cout, "Hello, world").operator<<(std::endl);
без ADL. Вот что Бьярн имел в виду под многословием.
Я исправился. Как отмечает Лахлан Истон , это не опечатка, а ошибка в книге. У меня нет доступа к этой книге, поэтому я не мог прочитать этот абзац и понять это сам. Я сообщил об этой ошибке Бьярну, чтобы он исправил ее.
Смешной. Тот же пример есть в Википедии и
Несомненно, это ошибка в книге. Тем не менее пример
std::operator<<(std::cout, "Hello, world").operator<<(std::endl);
показывает, как ADL помогает уменьшить многословие.Спасибо gx_ за указание на мою ошибку .
источник
std::operator<<
) и написал целый абзац с неверной информацией. Это действительно заставляет вас поверить, что правила ADL изменились и что компиляторы теперь не работают.std::operator<<(std::cout, "Hello, world").operator<<(std::endl);
(см. Не-членoperator<<
и членoperator<<
)Подсказка содержится в названии «поиск, зависящий от аргументов».
Это поиск неквалифицированных имен функций, который работает в зависимости от аргументов .
Это не имеет ничего общего с Lookup для аргументов.
Бьярн оговорился.
источник
У меня нет книги, но похоже, что это ошибка в книге. Отсутствие квалификатора пространства имен не имеет ничего общего с ADL. Так и должно быть
std::endl
.источник
std::cout
он говорил о поискеoperator<<
, а неendl
.Да, это ошибка - пример неверно сформирован и не должен компилироваться. ADL применяется к неквалифицированным именам функций, которые представляют выражения вызова функций.
endl
Идентификационное выражение, пытающееся выполнить поискstd::endl
.endl
не вводит выражение вызова функции, поэтому для него не используется поиск, зависящий от аргументов, используется только неквалифицированный поиск, поэтому он не найдетstd::endl
должным образом.Более простой и правильный пример:
#include <vector> int main() { std::vector<int> x, y; swap(x,y); // calls std::swap due to ADL }
Таким образом, перед поиском вызова функции (например
f(x,y,z)
) с неквалифицированным идентификатором (напримерf
), сначала параметры функции (например,x,y,z
анализируются ), чтобы определить их тип. Список связанных пространств имен формируется на основе типов (например, включающее пространство имен определения типа является связанным пространством имен). Затем в этих пространствах имен выполняется дополнительный поиск функции.Целью примера Бьярна является демонстрация ADL
std::operator<<
функции, а неstd::endl
. Это требует дополнительного понимания того, что перегруженные операторы на самом деле являются выражениями вызова функций,x << y
значитoperator<<(x,y)
, иoperator<<
является неквалифицированным именем, и поэтому к нему применяется ADL. Тип LHS этоstd::ostream
так ,std
это Связанное пространство, и , следовательно ,std::operator<<(ostream&, ...)
будет найден.Исправленный комментарий должен гласить:
источник