2010-09-29 3 views
4

J'ai un objet:appel carte :: trouver un argument const

map<A*, string> collection; 

Je voudrais appeler la fonction carte :: trouver, mais la valeur que j'ai la clé est const, comme dans le le code ci-dessous, qui ne compile pas:

const A* a = whatever(); 
collection.find(a); 

les travaux de code suivant et effectue l'équivalent de l'opération de recherche:

const A* a = whatever(); 
map<A*, string>::iterator iter; 
for(iter = collection.begin(); iter != collection.end(); ++iter) 
    if(iter->first == a) 
     break; 
// iter now contains the result or map::end (just like map::find) 

Mais il n'est probablement pas aussi efficace que la fonction de recherche de membre, et il est également moche et masque l'intention du code.

Comment puis-je appeler la fonction de recherche?

Merci

Edit:

J'utilise intentionnellement un type de pointeur pour la clé sur la carte. Le comportement que je souhaite est que la carte utilise l'égalité de pointeur pour les clés. (Tout comme dans mon code de boucle)

+0

Quelle erreur de compilation obtenez-vous? – JoshD

Répondre

11

Comparer les pointeurs n'a rien à voir avec elle. L'OP peut ou non avoir besoin d'une opération de comparaison personnalisée; il me semble qu'ils cherchent juste un objet spécifique par son adresse, ce qui semble parfaitement raisonnable. Les deux premières réponses semblent avoir manqué le point que find() ne compile pas pendant qu'une recherche manuscrite fonctionne.

L'appel find() ne compilera pas car vous lui passez le mauvais type à rechercher. map :: find() s'attend à ce que son argument soit du même type que le type de clé de la carte, qui est A *. Vous passez un const A *, qui n'est pas implicitement convertible en A * (mais est comparable à un A *, c'est pourquoi la recherche manuscrite fonctionne). La conversion implicite ne fonctionne que dans l'autre sens (A * à const A *, pas const A * à A *).

Il est possible que vous utilisiez const A * au lieu de A * comme clé de carte; Selon ce que vous utilisez pour la carte, cela peut être pratique ou non. Si vous avez besoin que la clé de la carte soit A *, vous devez passer un A * pour trouver(), ce qui signifie soit commencer par un A * comme cible de recherche, ou si vous ne pouvez l'obtenir qu'à partir de son original source comme const A *, en utilisant find (const_cast < A * > (a)) pour le transformer en un pointeur vers non-const (ce qui n'est pas la même chose qu'un pointeur non const, un point qui confond beaucoup de C/C++ codeurs). Habituellement, const_cast est déconseillé, mais ici c'est sûr car vous ne faites que comparer le pointeur, sans le déréférencer.

+0

Oui, ceci est une description détaillée de mon problème. Il semble que l'utilisation d'une const_cast est la seule façon de procéder, mais il est frustrant de ne pas avoir besoin de lancer une "recherche manuscrite". Je suis presque tenté d'utiliser la recherche manuscrite, puisque je déteste les castes. La fonction de recherche de bibliothèque d'origine a-t-elle pu être écrite pour fonctionner dans ce scénario ou existe-t-il une limitation dans le langage C++? – bartsimpson

+2

Le gros avantage de map :: find() sur une simple recherche linéaire est que c'est beaucoup plus rapide si la collection est grande. –

1

Vous pouvez toujours retirer la const

const A* a = whatever(); 
collection.find(const_cast<A*>(a)); 
+0

Merci, cela fonctionne, mais j'espère qu'il y a un moyen sans utiliser un cast – bartsimpson

+0

@bartsimpson - Vous pouvez modifier votre carte pour contenir 'const A *' –

Questions connexes