Perché ostream_iterator non funziona come previsto?

Inutile dire altro che il seguente codice:

#include  #include  #include  #include  using namespace std; typedef pair PAIR; ostream& operator <<(ostream& os, const PAIR& r) { return os << r.first; } int main() { vector coll; cout << coll[0]; // OK. // The following line will cause a compilation error! Why??? copy(coll.begin(), coll.end(), ostream_iterator(cout)); } 

Il problema è che la ricerca del nome non trova il tuo operator<<(ostream& os, const PAIR& r) . Il codice che tenta di richiamare l' operator<< trova da qualche parte all'interno di ostream_iterator<> che è esso stesso all'interno dello spazio dei nomi std . La ricerca del nome cerca la funzione giusta all'interno di ostream_iterator<> e lo spazio dei nomi std ; la ricerca dipendente dall'argomento non aiuta qui perché entrambi i parametri si trovano anche nello spazio dei nomi std .

Quindi, il mio suggerimento è (1) di avvolgere il tuo operatore nello namespace std { } , ma quello è UB, IIRC. Oppure (2) crea una struct che eredita da std::pair per definire un nuovo tipo nel tuo spazio dei nomi e usa l'ADL per trovare il tuo operator<<() .

AGGIORNARE:

Il mio terzo suggerimento è di usare un manipolatore personalizzato per stampare la coppia.

Per quanto riguarda il mio secondo suggerimento, se puoi usare C ++ 11, ereditare da std::pair dovrebbe essere facile (non testato):

 struct PAIR : std::pair { using std::pair::pair; }; 

Se non puoi usare C ++ 11, ti suggerisco di usare un manipolatore personalizzato.

Questo è un problema comune: in una parola, il tuo operator<< non è visto durante l'istanziazione di std::ostream_iterator .

Durante la creazione di istanze, il nome cerca i tentativi di trovare un operator<< nello spazio dei nomi std . I candidati verranno trovati, quindi nessun altro namespace sarà considerato (e, in particolare, non lo spazio dei nomi globale). Quindi, entra in gioco la risoluzione di sovraccarico: nessuno del sovraccarico corrisponde al tipo di argomento, quindi la compilazione fallisce. Si noti che la ricerca dipendente dall'argomento non è di alcun aiuto in questo caso poiché std::pair è anche nello spazio dei nomi std .

Hai due soluzioni:

  • Racchiudi il tuo operator<< nello namespace std { } , anche se dovresti sapere che questo è illegale secondo lo standard (17.4.3.1)
  • Evita std::copy per questa attività e usa std::for_each (con un functor "old std::for_each " o lambda)