2011-07-30 15 views
15

Considere el siguiente programa:¿Dónde debería definir operator >> para mi especialización de std :: pair?

#include <iostream> 
#include <iterator> 
#include <vector> 
#include <utility> 
using namespace std; //just for convenience, illustration only 

typedef pair<int, int> point; //this is my specialization of pair. I call it point 

istream& operator >> (istream & in, point & p) 
{ 
    return in >> p.first >> p.second; 
} 

int main() 
{ 
    vector<point> v((istream_iterator<point>(cin)), istream_iterator<point>()); 
    //    ^^^       ^^^   
    //extra parentheses lest this should be mistaken for a function declaration 
} 

Esta falla al compilar porque tan pronto como ADL encuentra el operador >> en el espacio de nombres std que no tiene en cuenta el alcance global de más, independientemente de si el operador se encuentra en std era una candidato viable o no. Esto es bastante inconveniente. Si coloco la declaración de mi operador >> en el espacio de nombres estándar (que es técnicamente ilegal), el código se compila bien como se esperaba. ¿Hay alguna manera de resolver este problema que no sea hacer point mi propia clase en lugar de typedefing como una especialización de una plantilla en el espacio de nombres std?

Gracias de antemano

+0

No estamos especializados 'std :: pair' aquí. Creo que esto tiene más que ver con la forma en que se analiza el código con plantilla que con la propia ADL. –

Respuesta

11

Adición de una sobrecarga de operator>> en namespace std está prohibido, pero la adición de una especialización de plantilla veces se permite.

Sin embargo, no hay tipos definidos por el usuario aquí, y los operadores en tipos estándar no son suyos para redefinir. La especialización operator>>(istream&, pair<mytype, int>) sería razonable.


sección [namespace.std] (sección 17.6.4.2.1 de n3290) dice

El comportamiento de un programa en C++ no está definido si se agrega declaraciones o las definiciones de espacio de nombres std o para un espacio de nombres dentro del espacio de nombres std a menos que se especifique lo contrario. Un programa puede agregar una especialización de plantilla para cualquier plantilla de biblioteca estándar al espacio de nombre std solo si la declaración depende de un tipo definido por el usuario y la especialización cumple los requisitos de biblioteca estándar para la plantilla original y no está explícitamente prohibido.

(el énfasis es mío)

+0

¿Su respuesta implica que la respuesta a mi pregunta es *** no *** y debería convertir 'point' en una clase separada? –

+0

Hablando por Ben Voigt, diría que sí, lo hace. –

+0

@Benoit: Por cierto, no entiendo que los operadores en tipos estándar no sean míos para _re_define. No hay operador >> para el par, así que no estoy -definiendo nada, ¿verdad? –

Cuestiones relacionadas