Большинство манипуляторы потоков 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?
Ни один из этих вопросов и ни один ответ на них не затрагивают работу вывода аргумента шаблона, который должен предшествовать разрешению перегрузки, но должен помогать последнему.
Последующий вопрос: Как работает разрешение перегрузки, когда аргумент является перегруженной функцией?