¿Por qué ostream_iterator no funciona como se esperaba?

No hace falta decir algo más que el siguiente código:

#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)); } 

El problema es que la búsqueda de nombre no encuentra su operator<<(ostream& os, const PAIR& r) . El código que intenta invocar al operator<< está en algún lugar dentro del ostream_iterator<> que está dentro del std nombres std . La búsqueda de nombres busca la función correcta dentro de ostream_iterator<> y el std nombres ostream_iterator<> ; la búsqueda dependiente del argumento no ayuda aquí porque ambos parámetros están también en el std nombres std .

Entonces, mi sugerencia es (1) envolver su operador en el namespace std { } , pero eso es UB, IIRC. O (2) cree una estructura que hereda de std::pair para definir un nuevo tipo en su espacio de nombres, y usando la ADL para encontrar su operator<<() .

ACTUALIZAR:

Mi tercera sugerencia es usar un manipulador personalizado para imprimir el par.

En cuanto a mi 2da sugerencia, si puedes usar C ++ 11, heredar de std::pair debería ser fácil (no probado):

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

Si no puede usar C ++ 11, entonces sugiero usar un manipulador personalizado.

Este es un problema común: en una palabra, su operator<< no se ve al crear instancias de std::ostream_iterator .

Durante la creación de instancias, la búsqueda de nombres intenta encontrar un operator<< en el espacio de nombres std . Se encontrarán los candidatos, por lo que no se considerarán otros espacios de nombres (y, particularmente, no el espacio de nombres global). Entonces, la resolución de sobrecarga entra en juego: ninguna de las sobrecargas coincide con el tipo de argumento, por lo que la comstackción falla. Tenga en cuenta que la búsqueda dependiente del argumento no sirve de nada, ya que std::pair también está en el espacio de nombres std .

Tienes dos soluciones:

  • Incluya su operator<< en namespace std { } , aunque debe saber que esto es ilegal según el estándar (17.4.3.1)
  • Evite std::copy para esta tarea y use std::for_each (ya sea con un functor 'old-fashioned' o lambda)