c++ - example - mapa cplusplus
¿Cómo evitar el reparto constante para el acceso al mapa? (2)
Tengo el siguiente problema:
std::map<A*,double> map;
void getColor(A const * obj){
double d = map[obj]; // does not compile wihtout const_cast<A*>(obj)
// do something
}
Tengo un mapa std::map
(en algún lugar) que almacena los punteros a los objetos A
Tengo una función getColor
que no manipula los objetos A
y, por lo tanto, lleva un puntero a una const A
como entrada.
La función getColor
no se compilará sin utilizar un const_cast.
El lanzamiento constante es un problema de diseño, pero no sé cómo evitarlo si no quiero hacer que las claves en el map
constantes .
Cualquier ayuda apreciada.
Hay dos posibles escenarios aquí:
La función sabe / espera que
obj
ya esté presente en el mapa, y está usando[]
para su comodidad.Está utilizando
[]
para todo su potencial, es decir, espera que agregueobj
al mapa si no está ya allí.
En la situación 2, tienes un error en la firma getColor
. Dado que potencialmente puede pasar obj
a un lugar donde se almacenará como A*
, es incorrecto que acepte una const A*
solamente. Tenga en cuenta que incluso si una función no modifica un objeto en sí, sino que lo pasa a algún lugar donde pueda modificarse, en realidad lo está modificando indirectamente y, por lo tanto, debería tomarlo como no const
.
En la situación 1, depende de tu versión de C ++. C ++ 14 introdujo una sobrecarga de plantillas de find
y funciones miembro relacionadas de std::map
que toman cualquier cosa comparable con Key
lugar de solo Key
. Por lo tanto, podría modificar la función de esta manera:
void getColor( A const * obj){
doubel d = map.find(obj)->second;
// do something
}
Tenga en cuenta que para que esto funcione, también necesita cambiar el tipo de mapa para usar un comparador transparente: std::map<A*,double, std::less<>> map;
(como lo señaló por primera vez la respuesta de @Ley ).
Si estás atascado con C ++ 11 o anterior, estás fuera de suerte y tendrás que vivir con const_cast
. Tenga en cuenta que con un comentario adecuado, un const_cast
es perfectamente seguro y aceptable en este caso (sin mencionar la única manera de proceder sin cambiar el tipo de map
). De nuevo, debe usar find
o quizás at
lugar de []
, ya que no desea insertar en el mapa.
Si puede permitirse cambiar a C ++ 14, puede configurar su mapa para que use un comparador transparente (esto funcionará ya que un puntero de const puede compararse con un puntero de no const):
std::map<A*,double, std::less<>> map;
// ^^^^^^^^^^^
// enable transparent comparator on this map
void getColor( A const * obj){
auto it = map.find(obj);
assert(it != map.end());
double d = it->second;
// do something
}
Tenga en cuenta que deberá usar std::map::find()
lugar de std::map::operator[]
, ya que este último no tiene una versión transparente .