2014-01-04 2 views
7

Я смотрел запись в Википедии argument-dependent lookup, и (янв 04, 2014) следующий пример был дан:Почему «std :: endl» требует квалификацию пространства имен при использовании в выражении «std :: cout << std :: endl;», учитывая зависящий от аргумента поиск?

#include<iostream> 

int main() 
{ 
    std::cout << "Hello World, where did operator<<() come from?" << std::endl; 
} 

... со следующим комментарием:

Обратите внимание, что станд :: епсИ является функцией, но она нуждается в полной квалификации, , поскольку он используется в качестве аргумента для оператора < < (std :: endl - забава ction указатель, а не вызов функции).

Мое мнение, что комментарий неверен (или просто неясен). Я рассматриваю изменение комментария сказать, вместо

Обратите внимание, что STD :: епсИ нуждается в полной квалификации, потому что ADL не относится к аргументам вызова функции; он относится только к имени функции.

Я исправлю, что комментарий к Википедии неверный? Является ли мое предложение правильным? (I.e., является ли мое понимание ADL правильным в этом примере?)

+0

По той же причине, почему 'cout' нуждается в квалификации пространства имен. – Mehrdad

+0

@Mehrdad Хотя, возможно, если ADL ** ** использовались для поиска имен, используемых как * другие аргументы * для функции, имя можно было бы найти с помощью ADL. –

+0

ADL означает, что имя функции может быть выведено из аргументов, а не наоборот. –

ответ

10

Нет ничего плохого в том, что говорит Википедия.

std::cout << "Hello World, where did operator<<() come from?" << std::endl 

эквивалентно следующим образом (в предположении operator<< реализован в виде свободной функции)

operator<<(
    operator<<(std::cout, "Hello World, where did operator<<() come from?"), 
    std::endl) 

, которая ясно требует квалификации пространства имен для обоих cout и endl, потому что это аргумент-зависимой поиска (из функция), а не «поиск аргументов».
Аргументы определяют функцию, которую нужно вызывать, а не наоборот.

+0

Хорошая точка. Вложенность, когда написано, дает понять, что 'std :: endl' является ** единственным ** аргументом в' namespace std' для * первого * вызова 'operator <<', и, следовательно, необходимо вызвать ADL. Однако: не правда ли, что комментарий, появляющийся в Википедии, * (std :: endl - это указатель на функцию, а не вызов функции) *, не имеет значения (и, следовательно, вводит в заблуждение)? –

+0

@ DanNissenbaum: Полагаю, я мог бы согласиться, что это немного вводит в заблуждение, потому что если бы существовала функция 'std :: get_endl()', которая возвращала 'std :: endl', это был бы вызов функции, но это было бы неважно для целого Проблема ADL. Это своего рода обходной способ подумать об этом, поэтому нередко интерпретировать его таким образом, но если вы это сделаете, я предполагаю, что это запутанно. То, что вы сказали, конечно, не так, а может быть, пойти и изменить его? – Mehrdad

+0

@ DanNissenbaum: Я думаю, что Википедия хотела сделать, это * counter * возможный аргумент, * «Но' endl (std :: cout) 'не требует квалификации пространства имен!" *, ​​На который отвечает * "' endl' здесь - вызов функции, а не указатель функции "*. Это имеет смысл в этом контексте, но если вы читаете это буквально, я могу понять, почему это вводит в заблуждение. – Mehrdad

1

Правило в Википедии. Тот факт, что один из операндов operator<< находится в пространстве имен std, вызывает поиск имени, включающий объявления operator<< из пространства имен std в заданных параметрах-кандидатах, поданных на разрешение перегрузки.

+0

Обратите внимание, что я прошу не искать поиск * функции *, а вместо этого поиск * другого аргумента * функции. Другими словами, поскольку * хотя бы один аргумент * находится в 'namespace std', возможно, ADL может использоваться для поиска в этом пространстве имен, чтобы найти * другие * аргументы для одной и той же функции. –

+0

@DanNissenbaum Это будет зависящий от функции поиск ~ для имен аргументов, а не зависящий от аргументов поиск имен функций. – jthill

+0

Поэтому я думаю, что мои предложенные изменения верны - согласно этим рассуждениям. Возможно, я не понимаю. –

3

И оригинальная фразировка, и ваша формулировка верны.

std::endl a функция. C++03 spec section 27.6 [lib.iostream.format]:

Заголовок <ostream> синопсис

namespace std { 
template <class charT, class traits = char_traits<charT> > 
class basic_ostream; 
typedef basic_ostream<char> ostream; 
typedef basic_ostream<wchar_t> wostream; 
template <class charT, class traits> 
basic_ostream<charT,traits>& endl(basic_ostream<charT,traits>& os); 
... 

В этом контексте std::endl функция (точнее, функция указателя, в который он распадается) в настоящее время передается в качестве аргумента operator<< , Поскольку это аргумент, ADL не применяется.

+0

Если это так, я думаю, что утверждение в Википедии '(std :: endl - это указатель на функцию, а не вызов функции)', не имеет отношения к ADL и, следовательно, вводит в заблуждение. Я хотел бы удалить его. –

+0

Это не технически неправильно ... Но я согласен, что это кажется несущественным и потенциально обманчивым, детальным. Поэтому я бы сказал, пойдите для этого. – Nemo

Смежные вопросы