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 el operador de asignación predeterminado no podrá generarse.
Me gustaría tener un pair<T&, U&>
y poder asignarle otro par (de valores o referencias) y modificar los objetos apuntados.
7 answers
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.
Note que dije "confiablemente". Algunos compiladores comunes aún 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 mientras implementan el colapso de referencia (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 compiladores 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<int&, int&> t = boost::tie(a, b);
t.get<0>() = 1;
t.get<1>() = 2;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:37
En C++11 se puede utilizar std::pair<
std::reference_wrapper
<T>, std::reference_wrapper<U>>
y los objetos de ese tipo se comportarán exactamente como quieras.
Creo que sería legal tener una std::pair
referencias de vivienda. std::map
usa std::pair
con un tipo const
, después de todo, que no se puede asignar a ninguno de los dos.
Me gustaría tener un
pair<T&, U&>
y poder asignarle otro par
La asignación no funcionará, ya que no se pueden restablecer las referencias. Sin embargo, puede copiar-inicializar dichos objetos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-22 13:39:01
Tienes razón. Puede crear un par de referencias, pero ya no puede usar operator =
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-22 13:38:16
Estaba pensando en la misma línea que usted, creo. Escribí la siguiente clase para rascar este picor en particular:
template <class T1, class T2> struct refpair{
T1& first;
T2& second;
refpair(T1& x, T2& y) : first(x), second(y) {}
template <class U, class V>
refpair<T1,T2>& operator=(const std::pair<U,V> &p){
first=p.first;
second=p.second;
return *this;
}
};
Te permite hacer cosas horribles como:
int main (){
int k,v;
refpair<int,int> p(k,v);
std::map<int,int>m;
m[20]=100;
m[40]=1000;
m[60]=3;
BOOST_FOREACH(p,m){
std::cout << "k, v = " << k << ", " << v << std::endl;
}
return 0;
}
(recuerde las inclusiones relevantes).
El rudo es, por supuesto, que las referencias a k
y v
que estoy asignando están ocultos dentro de p
.
Casi se vuelve bonito de nuevo si haces algo como esto:
template <class T1,class T2>
refpair<T1,T2> make_refpair (T1& x, T2& y){
return ( refpair<T1,T2>(x,y) );
}
Que te permite hacer un bucle como este:
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++.)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-07 13:58:43
No se que es "malo" con std::pair
en C++03 pero si lo reimplazo ingenuamente, no tengo ningún problema con él, (usando el mismo compilador gcc
y clang
).
double a = 1.;
double b = 2.;
my::pair<double, double> p1(5., 6.);
my::pair<double&, double&> p2(a, b);
p2 = p1; // a == 5.
Así que una solución podría ser (1) reimplementar pair
(en un espacio de nombres diferente), o (2) especializarse para std::pair<T&, T&>
, 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<class T1, class T2>
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<class U1, class U2> pair(pair<U1, U2> const& p) : first(p.first), second(p.second){}
template<class U1, class U2>
pair& operator=(const pair<U1, U2>& p){
first = p.first;
second = p.second;
return *this;
}
};
template<class T1, class T2>
pair<T1, T2> make_pair(T1 t1, T2 t2){
return pair<T1, T2>(t1, t2);
}
}
(2) Y aquí es una especialización de std::pair
(algunas personas pueden me quejo de que estoy sobrecargando / especializándome con el espacio de nombres std
, pero creo que está bien si es para extender las capacidades de la clase)
namespace std{
template<class T1, class T2>
struct pair<T1&, T2&>{
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<class U1, class U2> pair(pair<U1, U2> const& p) : first(p.first), second(p.second){}
template<class U1, class U2>
pair& operator=(const pair<U1, U2>& p){
first = p.first;
second = p.second;
return *this;
}
};
}
Tal vez me falta algo obvio, puedo editar la respuesta si algunos defectos obvios, se señalan.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-18 02:32:24
Terminé resolviendo un problema similar simplemente construyendo una estructura realmente simple. Ni siquiera me preocupé por el operador de asignación ya que el predeterminado debería funcionar bien.
template<class U, class V>
struct pair
{
pair(U & first, V & second): first(first), second(second) {}
U & first;
V & second;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-22 04:56:50