c++ - strtoint - std:: par de referencias
stoi is not a member of std (7)
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<T&, U&>
y poder asignarle otro par
La asignación no funcionará, ya que no puede restablecer las referencias. Sin embargo, puede copiar-inicializar tales objetos.
¿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<T&, U&>
y poder asignarle otro par (de valores o referencias) y modificar los objetos apuntados.
En C ++ 11 puede usar std::pair<
std::reference_wrapper
<T>, std::reference_wrapper<U>>
y los objetos de ese tipo se comportarán exactamente como lo desee.
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 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 el pair
(en un espacio de nombre diferente), o (2) especializar 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í 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<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 está perdiendo algo obvio, puedo editar la respuesta si algunos defectos obvios son puntiagudos.
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 compiladores 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 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;
Pensaba en la misma línea que tú, creo. Escribí la siguiente clase para borrar este particular picor:
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 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 <class T1,class T2>
refpair<T1,T2> make_refpair (T1& x, T2& y){
return ( refpair<T1,T2>(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 ++).
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<class U, class V>
struct pair
{
pair(U & first, V & second): first(first), second(second) {}
U & first;
V & second;
}
Tienes razón. Puede crear un par de referencias, pero ya no puede usar operator =
.