2015-11-28 17 views
26

Mam następujący kod:Obscure C++ operator przeciążenia

#include <iostream> 

using namespace std; 

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

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

i jakoś to działa - wyjście "cześć cześć". Jak to zinterpretować przez kompilator? Nie rozumiem, w jaki sposób można wstawić funkcję do strumienia.

+5

Istnieje przeciążony 'operator <<', który akceptuje funkcję i wywołuje ją. Jak dokładnie jest to niejasne? –

+6

To jest sposób, w jaki działają różne przeciążenia 'std :: endl' lub' std :: flush'. –

Odpowiedz

30

std::ostream ma operator<< przeciążenia, który odbiera wskaźnik do funkcji z podpisem, takich jak ta, którą napisał (number 11 in this list):

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

który właśnie nazywa podana funkcja przekazuje się jako argument. To przeciążenie (wraz z kilkoma podobnymi) służy do implementowania manipulatorów strumieniowych, tj. Rzeczy, które wyprowadzasz w strumieniu z << i zmienia stan stamtąd strumienia. Na przykład, nasza wersja z (niesłusznie) wszechobecny std::endl mogą być realizowane jako

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

, które mogą być następnie dokładnie wykorzystywane jako „normalne” std::endl:

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

(faktyczna realizacja jest na matrycy i nieco bardziej skomplikowany, ponieważ musi działać nawet z szerokimi strumieniami, ale masz pomysł)

8

std::ostream::operator<< ma przeciążenie, które przyjmuje funkcję jako parametr; a ciałem tego przeciążenia jest przywoływanie podanej funkcji. To jest dokładnie to, jak działa endl. endl jest rzeczywiście funkcja podobna do:

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

Musiałbym sprawdzić, ale nie sądzę, że istnieje jakiś szablon (ignorując fakt, że 'ostream' jest instatiacją' basic_ostream'). AFAIR, istnieją tylko dwa przeciążenia dla funkcji pobierających 'ostream' i' ios_base'. –

+0

@UlrichEckhardt cóż, parametry szablonu to 'CharT' i' Traits'. Dokonam edycji, aby wyjaśnić, ponieważ jest to mylące, jak wskazujesz. –