Подтвердить что ты не робот

Перегрузка операторов Obscure С++

У меня есть следующий код:

#include <iostream>

using namespace std;

ostream& f(ostream& os) {
    return os << "hi";
}

int main() {
    cout << "hello " << f << endl;
    return 0;
}

И как-то это работает - выход "привет привет". Как это интерпретируется компилятором? Я не понимаю, как функция может быть вставлена ​​в поток.

4b9b3361

Ответ 1

std::ostream имеет перегрузку operator<<, которая получает указатель на функцию с сигнатурой, например, написанную вами (номер 11 в этом списке):

basic_ostream& operator<<(
    std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&) );

который просто вызывает данную функцию, передающую себя как аргумент. Эта перегрузка (наряду с несколькими аналогичными другими) позволяет вам создавать манипуляторы потока, т.е. Материал, который вы выводите в потоке с помощью <<, и изменяет состояние потока оттуда. Например, наша версия (неправильно) вездесущая std::endl может быть реализована как

std::ostream &myendl(std::ostream &s) {
    s<<'\n';
    s.flush();
    return s;
}

который затем можно использовать точно так же, как "обычный" std::endl:

std::cout<<"Hello, World!"<<myendl;

(фактическая реализация шаблонизирована и немного сложнее, потому что она должна работать даже с широкими потоками, но вы получили эту идею)

Ответ 2

std::ostream::operator<< имеет перегрузку, которая принимает функцию как параметр; и тело этой перегрузки должно вызвать указанную функцию.

Именно так работает endl. endl - фактически функция, подобная:

ostream &endl(ostream &os)
{
    os << '\n'; 
    os.flush(); 
    return os;
}