Hilo
Sobrecarga del operador [] (marcelinux) 2018-10-24 09:03:13
Hola de nuevo.
Sigo con mi lento progreso en el conocimiento de C++
Esta vez tengo dificultades en el capítulo de sobrecarga de operadores de la 3ª edición del libro de Stroustrup.
Concretamente en el apartado 11.8 Subscripting (página 286) muestra un ejemplo donde define el operator[]
En los dos compiladores que lo he probado me devuelve error y, aunque sé el motivo y lo que se pretende, no sé la forma en que debería solventarlo.
Transcribo el apartado completo y los errores que me devuelven los compiladores MSVC++ 2008 sobre Windows XP y GCC 6.3 sobre Debian 9.
[cita:The C++ programming language (3th edition), página 286]
11.8 Subscripting [over.subscript]
An operator[] function can be used to give subscripts a meaning for class objects. The second argument (the subscript) of an operator[] function may be of any type. This makes it possible to define vectors, associative arrays, etc.
As an example, let us recode the example from §5.5 in which an associative array is used to write a small program for counting the number of occurrences of words in a file. There, a function is used. Here, an associative array type is defined:
class Assoc {
struct Pair {
string name;
double val;
Pair(string n = "", double v = 0) : name(n), val(v) {}
};
vector<Pair> vec;
Assoc(const Assoc&); // private to prevent copying
Assoc& operator=(const Assoc&); // private to prevent copying
public:
Assoc() {}
double& operator[](const string&);
void print_all() const;
};
An Assoc keeps a vector of Pairs. The implementation uses the same trivial and inefficient search method as in §5.5:
double& Assoc::operator[](const string& s)
// search for s; return its value if found; otherwise, make a new
// Pair and return the default value 0
{
for (vector<Pair>::const_iterator p = vec.begin(); p != vec.end(); ++p)
if (s == p->name) return p-> val;
vec.push_back(Pair(s,0)); // initial value: 0
return vec.back().val; // return last element(&16.3.3)
}
Because the representation of an Assoc is hidden, we need a way of printing it:
void Assoc::print_all() const
{
for (vector<Pair>::const_iterator p = vec.begin(); p != vec.end(); ++p)
cout << p-> name << ": " << p->val << '\n';
}
Finally, we can write the trivial main program:
int main()
{
string buf;
Assoc vec;
while (cin >> buf) vec[buf]++;
vec.print_all();
return 0;
}
A further development of the idea of an associative array can be found in §17.4.1.
An operator[]() must be a member function.
[fin de cita]
El error se produce en return p-> val;
MSVC++ 2008: error C2440: 'return' : no se puede realizar la conversión de 'const double' a 'double &'
GCC 6.3: In member function ‘double& Assoc::operator[](const string&)’:
error: binding ‘const double’ to reference of type ‘double&’ discards qualifiers
if (s == p->name) return p-> val;
~~~^~~
Se supone que debe devolver una referencia, sin embargo p-> val es un valor double.
Sin embargo, si elimino la referencia devuelta:
double Assoc::operator[](const string& s)
no podré usar:
vec[buf]++;
¿Qué me falta por entender?
_______________________________________________
Lista de correo Cconclase Cconclase@listas.conclase.net
http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
Bajas: http://listas.conclase.net/index.php?gid=2&mnu=FAQ
Re: Sobrecarga del operador [] (Carlos Ernesto Obregon Suarez) 2018-10-24 12:25:17
Podría ser porque usas const_iterator para recorrer el vector, cuando
devuelves un valor apuntado por un iterador constante el valor devuelto es
una referencia constante.
Es posible que retorne const double& cuando lo que necesitas es double&.
Prueba utilizando iterator y no const iterator o cambia el valor de retorno
a const double &
El mié., 24 de oct. de 2018 6:04 AM, marcelinux <marcelinator@gmail.com>
escribió:
> Hola de nuevo.
> Sigo con mi lento progreso en el conocimiento de C++
> Esta vez tengo dificultades en el capítulo de sobrecarga de operadores de
> la 3ª edición del libro de Stroustrup.
> Concretamente en el apartado 11.8 Subscripting (página 286) muestra un
> ejemplo donde define el operator[]
> En los dos compiladores que lo he probado me devuelve error y, aunque sé
> el motivo y lo que se pretende, no sé la forma en que debería solventarlo.
> Transcribo el apartado completo y los errores que me devuelven los
> compiladores MSVC++ 2008 sobre Windows XP y GCC 6.3 sobre Debian 9.
>
> [cita:The C++ programming language (3th edition), página 286]
> 11.8 Subscripting [over.subscript]
> An operator[] function can be used to give subscripts a meaning for class
> objects. The second argument (the subscript) of an operator[] function may
> be of any type. This makes it possible to define vectors, associative
> arrays, etc.
> As an example, let us recode the example from §5.5 in which an associative
> array is used to write a small program for counting the number of
> occurrences of words in a file. There, a function is used. Here, an
> associative array type is defined:
>
> class Assoc {
> struct Pair {
> string name;
> double val;
> Pair(string n = "", double v = 0) : name(n), val(v) {}
> };
> vector<Pair> vec;
>
> Assoc(const Assoc&); // private to prevent copying
> Assoc& operator=(const Assoc&); // private to prevent copying
> public:
> Assoc() {}
> double& operator[](const string&);
> void print_all() const;
> };
>
> An Assoc keeps a vector of Pairs. The implementation uses the same trivial
> and inefficient search method as in §5.5:
>
> double& Assoc::operator[](const string& s)
> // search for s; return its value if found; otherwise, make a new
> // Pair and return the default value 0
> {
> for (vector<Pair>::const_iterator p = vec.begin(); p != vec.end();
> ++p)
> if (s == p->name) return p-> val;
>
> vec.push_back(Pair(s,0)); // initial value: 0
>
> return vec.back().val; // return last
> element(&16.3.3)
> }
>
> Because the representation of an Assoc is hidden, we need a way of
> printing it:
>
> void Assoc::print_all() const
> {
> for (vector<Pair>::const_iterator p = vec.begin(); p != vec.end();
> ++p)
> cout << p-> name << ": " << p->val << '\n';
> }
>
> Finally, we can write the trivial main program:
>
> int main()
> {
> string buf;
> Assoc vec;
> while (cin >> buf) vec[buf]++;
> vec.print_all();
> return 0;
> }
>
> A further development of the idea of an associative array can be found in
> §17.4.1.
> An operator[]() must be a member function.
>
> [fin de cita]
>
> El error se produce en return p-> val;
> MSVC++ 2008: error C2440: 'return' : no se puede realizar la conversión de
> 'const double' a 'double &'
> GCC 6.3: In member function ‘double& Assoc::operator[](const string&)’:
> error: binding ‘const double’ to reference of type ‘double&’
> discards qualifiers
> if (s == p->name) return p-> val;
> ~~~^~~
>
> Se supone que debe devolver una referencia, sin embargo p-> val es un valor
> double.
> Sin embargo, si elimino la referencia devuelta:
> double Assoc::operator[](const string& s)
> no podré usar:
> vec[buf]++;
>
> ¿Qué me falta por entender?
> _______________________________________________
> Lista de correo Cconclase Cconclase@listas.conclase.net
> http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
> Bajas: http://listas.conclase.net/index.php?gid=2&mnu=FAQ
_______________________________________________
Lista de correo Cconclase Cconclase@listas.conclase.net
http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
Bajas: http://listas.conclase.net/index.php?gid=2&mnu=FAQ
Re: Sobrecarga del operador [] (marcelinux) 2018-10-24 21:09:29
El pasado 2018-10-24 12:25:17, Carlos Ernesto Obregon Suarez escribió:
CEOS> Podría ser porque usas const_iterator para recorrer el vector, cuando
CEOS> devuelves un valor apuntado por un iterador constante el valor devuelto es
CEOS> una referencia constante.
CEOS> Es posible que retorne const double& cuando lo que necesitas es double&.
CEOS> Prueba utilizando iterator y no const iterator o cambia el valor de retorno
CEOS> a const double &
Muchas gracias.
Cambiando a un iterator no constante ha funcionado perfectamente.
Supongo que será una errata en el libro.
Pero ahora tengo claro que, al tener que devolver una referencia, el valor no debe ser constante. Y al desreferenciar el iterador constante, su valor es constante.
Bueno, más o menos :">
_______________________________________________
Lista de correo Cconclase Cconclase@listas.conclase.net
http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
Bajas: http://listas.conclase.net/index.php?gid=2&mnu=FAQ