2011-01-09 6 views
5

Ho il seguente codice:operatore di overload << sui problemi di concatenazione 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; 
} 

sto cercando di capire il motivo # 1 opere, mentre ci sono problemi quando si cerca di utilizzare l'operatore di overload concatenando come in # 2 che non riesce con il seguente errore (gcc 4.5.3 su 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]'

Tutto è invece bene se io definisco il mio operatore come

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

Sembra qualcosa correlato alla risoluzione di sovraccarico, in cui un oggetto inserito nell' ofstream per il quale esiste già un sovraccarico fornito (il const char * "etichetta" in questo caso) si interrompe dopo la risoluzione di sovraccarico, ma non posso realmente capire cosa sta succedendo esattamente qui. Mi piacerebbe avere un quadro chiaro di ciò che il compilatore sta cercando di fare ..

+1

Non so esattamente perché il compilatore si lamenta, ma l'overloading per 'ostream' (ovvero la classe di base comune) è la cosa giusta da fare, in quanto consente di utilizzarlo per tutti i tipi di flussi di output. –

risposta

16

Sulla linea:

f << "label: " << s; 

Perché la prima chiamata a operator<< restituisce un std::ostream &, il secondo non riesce a compilare: l'operando di sinistra per l'operatore non è più di tipo std::ofstream e il sovraccarico non è stato trovato.

Si consiglia di utilizzare effettivamente la seconda firma, in quanto non vedo alcun motivo per limitare il tipo da emettere a std::ofstream.

+0

Tuttavia, l'etichetta 'f << s <<": "' dovrebbe funzionare comunque! – Nawaz

+2

Puoi generalizzare ulteriormente la funzione per lavorare con qualsiasi tratto di carattere se usi la firma 'template std :: basic_ostream & operator << (std :: basic_ostream & s, const simple & obj);' – wilhelmtell