Как компилируется «std :: cout << std :: endl;»?

НаиболееIO потоковые манипуляторы являются обычными функциями со следующей сигнатурой:

std::ios_base& func( std::ios_base& str );

Однако некоторые манипуляторы (в том числе наиболее часто используемые -std::endl а такжеstd::flush) являются шаблонами следующей формы:

template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& func(std::basic_ostream<CharT, Traits>& os);

Затем, как составлениеstd::cout << std::endl; успешно, учитывая, что следующий пример завершается неудачей:

$ cat main.cpp 
#include <iostream>

int main()
{
    auto myendl = std::endl;
    std::cout << myendl;
}

$ g++ -std=c++11    main.cpp   -o main
main.cpp: In function ‘int main()’:
main.cpp:5:24: error: unable to deduce ‘auto’ from ‘std::endl’
     auto myendl = std::endl;
                        ^

Понятно, что контекст (вstd::cout << std::endl;) помогает компилятору устранить неоднозначностьstd::endl, Но каковы правила, регулирующие эту процедуру? Это похоже на реальную проблему для перегрузки разрешения, которая должна отвечать сразу на два вопроса:

Какая специализацияstd::endl<CharT, Traits>() делаетstd::endl Ссылаться на?Какая функция выполняетoperator<< Ссылаться на?

Вывод аргумента шаблона (1) должен произойти до разрешения перегрузки (2), но кажется, что (хотя бы некоторая часть) (2) должна быть выполнена для того, чтобы (1) был успешным.

Несколько связанные, но не повторяющиеся вопросы:

Работает ли std :: endl с cout и wcout?Почему endl (std :: cout) компилируетсяКак работает std :: flush?

Ни один из этих вопросов, ни ответы на них не касаются работы вывода аргументов шаблона, которая должна предшествовать разрешению перегрузки, но должна помогать последним.

Дополнительный вопрос: Как работает разрешение перегрузки, когда аргумент является перегруженной функцией?

Ответы на вопрос(4)

Ваш ответ на вопрос