std :: par de referencias

¿Es válido tener un std::pair de referencias? En particular, ¿hay problemas con el operador de asignación? De acuerdo con este enlace , no parece haber un tratamiento especial con operator =, por lo que no se podrá generar el operador de asignación predeterminado.

Me gustaría tener un pair y poder asignarle otro par (de valores o referencias) y modificar los objetos apuntados.

No, no puede hacer esto de manera confiable en C ++ 03, porque el constructor de pair toma referencias a T , y crear una referencia a una referencia no es legal en C ++ 03.

Tenga en cuenta que dije “de manera confiable”. Algunos comstackdores comunes todavía en uso (para GCC, probé GCC4.1, @Charles informaron GCC4.4.4) no permiten formar una referencia a una referencia, pero más recientemente lo permiten a medida que implementan colapso de referencia ( T& T es T si T es un tipo de referencia). Si su código usa tales cosas, no puede confiar en que funcione en otros comstackdores hasta que lo pruebe y vea.

Parece que quieres usar boost::tuple<>

 int a, b; // on the fly boost::tie(a, b) = std::make_pair(1, 2); // as variable boost::tuple t = boost::tie(a, b); t.get<0>() = 1; t.get<1>() = 2; 

En C ++ 11 puede usar std::pair< std::reference_wrapper , std::reference_wrapper> y los objetos de ese tipo se comportarán exactamente como lo desee.

Creo que sería legal tener referencias std::pair vivienda. std::map usa std::pair con un tipo const , después de todo, que no se puede asignar a ninguno.

Me gustaría tener un pair y poder asignarle otro par

La asignación no funcionará, ya que no puede restablecer las referencias. Sin embargo, puede copiar-inicializar tales objetos.

Tienes razón. Puede crear un par de referencias, pero ya no puede usar operator = .

Pensaba en la misma línea que tú, creo. Escribí la siguiente clase para borrar este particular picor:

 template  struct refpair{ T1& first; T2& second; refpair(T1& x, T2& y) : first(x), second(y) {} template  refpair& operator=(const std::pair &p){ first=p.first; second=p.second; return *this; } }; 

Te permite hacer cosas horribles como:

 int main (){ int k,v; refpair p(k,v); std::mapm; m[20]=100; m[40]=1000; m[60]=3; BOOST_FOREACH(p,m){ std::cout < < "k, v = " << k << ", " << v << std::endl; } return 0; } 

(recuerde que el relevante incluye).

La maldad es, por supuesto, que las referencias a k y v que estoy asignando están ocultas dentro de p . Casi se vuelve bonito de nuevo si haces algo como esto:

 template  refpair make_refpair (T1& x, T2& y){ return ( refpair(x,y) ); } 

Lo cual te permite hacer un loop así:

 BOOST_FOREACH(make_refpair(k,v),m){ std::cout < < "k, v = " << k << ", " << v << std::endl; } 

(Todos los comentarios son bienvenidos, ya que de ninguna manera soy un experto en C ++).

No sé qué está “mal” con std::pair en C ++ 03 pero si lo vuelvo a implementar ingenuamente, no tengo ningún problema con él, (usando el mismo comstackdor gcc y clang ).

 double a = 1.; double b = 2.; my::pair p1(5., 6.); my::pair p2(a, b); p2 = p1; // a == 5. 

Así que una solución podría ser (1) reimplementar el pair (en un espacio de nombre diferente), o (2) especializar para std::pair , o (3) simplemente usar C ++ 11 (donde std::pair para refs funciona fuera de la caja)

(1) Aquí está la implementación ingenua

 namespace my{ template struct pair{ typedef T1 first_type; typedef T2 second_type; T1 first; T2 second; pair(T1 const& t1, T2 const& t2) : first(t1), second(t2){} template pair(pair const& p) : first(p.first), second(p.second){} template pair& operator=(const pair& p){ first = p.first; second = p.second; return *this; } }; template pair make_pair(T1 t1, T2 t2){ return pair(t1, t2); } } 

(2) Y aquí está una especialización de std::pair (algunas personas pueden quejarse de que estoy molestando sobrecargar / especializarme con el std nombres std , pero creo que está bien si es para extender las capacidades de la clase)

 namespace std{ template struct pair{ typedef T1& first_type; /// @c first_type is the first bound type typedef T2& second_type; /// @c second_type is the second bound type first_type first; second_type second; pair(T1& t1, T2& t2) : first(t1), second(t2){} template pair(pair const& p) : first(p.first), second(p.second){} template pair& operator=(const pair& p){ first = p.first; second = p.second; return *this; } }; } 

Tal vez me está perdiendo algo obvio, puedo editar la respuesta si algunos defectos obvios son puntiagudos.

Terminé resolviendo un problema similar al construir una estructura realmente simple. Ni siquiera me preocupé por el operador de asignación, ya que el predeterminado debería funcionar bien.

 template struct pair { pair(U & first, V & second): first(first), second(second) {} U & first; V & second; }