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
objya esté presente en el mapa, y está usando[]para su comodidad.Está utilizando
[]para todo su potencial, es decir, espera que agregueobjal 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 .