2011-01-09 13 views
5

Mam następujący kod:przeciążony operator << na problemy konkatenacji ofstream

struct simple 
{ 
    simple (int a1, int a2) : member1(a1), member2(a2) {} 
    int member1; 
    int member2; 
}; 

std::ofstream &operator << (std::ofstream &f, const simple &obj) 
{ 
    f<<obj.member1<<", "<<obj.member2; 
    return f; 
} 
int main(int argc, const char *argv[]) 
{ 
    std::ofstream f("streamout.txt"); 

    simple s(7,5); 
    f << s;    //#1 This works 
    f << "label: " << s; //#2 This fails 

    return 0; 
} 

Próbuję zrozumieć, dlaczego prace # 1, podczas gdy istnieją problemy podczas próby użycia przeciążony operator łącząc go, jak w # 2, który nie powiedzie się z powodu następującego błędu (gcc 4.5.3 na MacOSX):

error: cannot bind 'std::basic_ostream' lvalue to 'std::basic_ostream&&' /GCC-FACTORY/4.5/INSTALL/lib/gcc/x86_64-apple-darwin10.5.0/4.5.3/../../../../include/c++/4.5.3/ostream:579:5: error: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char, _Traits = std::char_traits, _Tp = simple]'

wszystko jest w porządku, jeśli ja zamiast definiować mój operator jako

std::ostream &operator << (std::ostream &f, const simple &obj) 
{ ... } 

Brzmi to jak coś związanego z rozdzielczością przeciążenia, gdzie posiadanie czegoś włożonego do strumienia, dla którego istnieje już przewidziane przeciążenie (w tym przypadku "const char *" etykieta ") rozrywa się po przeciążeniu, ale nie mogę tak naprawdę rozumiem, co tu się właściwie dzieje. Chciałbym, aby uzyskać jasny obraz tego, co kompilator próbuje zrobić ..

+1

Nie wiem dokładnie dlaczego kompilator narzeka, ale przeciążanie dla 'ostream' (tj. Wspólnej klasy bazowej) jest poprawną czynnością, ponieważ pozwala na użycie go dla wszystkich rodzajów strumieni wyjściowych. –

Odpowiedz

16

rozmówcy:

f << "label: " << s; 

Ponieważ pierwsze wywołanie operator<< zwraca std::ostream &, drugi nie trafia do kompilacji: lewy operand do operatora nie jest już typu std::ofstream i nie znaleziono twojego przeciążenia.

Powinieneś naprawdę użyć drugiego podpisu, ponieważ nie widzę powodu, dla którego twój typ miałby być wyprowadzany na std::ofstream.

+0

Jednak etykieta 'f << s <<:" 'powinna działać! – Nawaz

+2

Możesz dalej generalizować funkcję do pracy z dowolnymi cechami znaków, jeśli użyjesz podpisu 'template std :: basic_ostream & operator << (std :: basic_ostream & s, const simple & obj);' – wilhelmtell

Powiązane problemy