2010-04-23 8 views
1

Considérez ce programme:"Constante forcée" dans std :: map <std :: vector <int>, double>>?

#include <map> 
#include <vector> 
typedef std::vector<int> IntVector; 
typedef std::map<IntVector,double> Map; 
void foo(Map& m,const IntVector& v) 
{ 
    Map::iterator i = m.find(v); 
    i->first.push_back(10); 
}; 
int main() 
{ 
    Map m; 
    IntVector v(10,10); 
    foo(m,v); 
    return 0; 
} 

Avec g ++ 4.4.0, je reçois son erreur de compilation:

test.cpp: In function 'void foo(Map&, const IntVector&)': 
test.cpp:8: error: passing 'const std::vector<int, std::allocator<int> >' as 'this' argument of 'void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = int, _Alloc = std::allocator<int>]' discards qualifiers 

Je me attends à cette erreur si j'utilisais Map::const_iterator l'intérieur foo, mais pas en utilisant un non const itérateur.

Qu'est-ce qui me manque, pourquoi ai-je cette erreur?

Répondre

6

Les touches d'une carte sont constantes. Une carte est un arbre, et vous ne pouvez pas vous contenter de changer les clés ou de casser ses invariants. Le value_type d'une carte avec Key et Value est std::pair<const Key, Value>, pour appliquer ceci.

Votre conception doit être modifiée. Si vous avez vraiment besoin de modifier la clé, vous devez supprimer l'élément, modifier sa clé et le réinsérer avec la nouvelle clé.

En ce qui concerne votre exemple en particulier, vous aurez un comportement indéfini (si cela a fonctionné). Votre carte est vide lorsque vous appelez le foo, donc l'itérateur retourné par find sera m.end(); l'élément n'existe pas. Mais ensuite vous allez modifier cet élément inexistant: ka-boom. Chaque fois que vous find quelque chose, vous devriez vérifier qu'il a été trouvé avant d'essayer de l'utiliser.

+1

Merci. Parfois, vous ne pouvez pas voir la forêt parce que tous les arbres sont sur le chemin. :-) –

Questions connexes