std::endl
- это шаблон функции. Обычно он используется в качестве аргумента оператора вставки <<
. В этом случае operator<<
рассматриваемого потока будет определяться как, например, ostream& operator<< ( ostream& (*f)( ostream& ) )
. Тип аргумента f
определен, поэтому компилятор будет знать точную перегрузку функции.
Это сравнимо с этим:
void f( int ){}
void f( double ) {}
void g( int ) {}
template<typename T> void ft(T){}
int main(){
f; // ambiguous
g; // unambiguous
ft; // function template of unknown type...
}
Но вы можете устранить неоднозначность с помощью некоторых подсказок:
void takes_f_int( void (*f)(int) ){}
takes_f_int( f ); // will resolve to f(int) because of `takes_f_int` signature
(void (*)(int)) f; // selects the right f explicitly
(void (*)(int)) ft; // selects the right ft explicitly
Это то, что обычно происходит с std::endl
при предоставлении в качестве аргумента operator <<
: есть определение функции
typedef (ostream& (*f)( ostream& ) ostream_function;
ostream& operator<<( ostream&, ostream_function )
И это позволит компилятору выбрать правильную перегрузку std::endl
, если она поступит, например, в. std::cout << std::endl;
.
Хороший вопрос!