tags:

views:

53

answers:

2

I have an object:

map<A*, string> collection;

I would like to call the map::find function, but the value I have for the key is const, like in the following code, which does not compile:

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

The following code works and performs the equivalent of the find operation:

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)

But it is probably not as efficient as the find member function, and it's also ugly and masks the intent of the code.

How can I call the find function?

Thanks

Edit:

I am intentionally using a pointer type for the key in the map. The behaviour I want is for the map to use pointer equality for the keys. (Just like in my loop code)

+1  A: 

You can always remove the const

const A* a = whatever();
collection.find( const_cast<A*>(a) );
Michael Anderson
Thanks, this works, but I am hoping there is a way without using a cast
bartsimpson
@bartsimpson - You could modify your map to contain `const A*`
Steve Townsend
+4  A: 

Comparing pointers has nothing to do with it. The OP may or may not need a custom compare operation; it looks to me like they're just looking for a specific object by its address, which seems perfectly reasonable. The first two answers seem to have missed the point that find() doesn't compile while a handwritten search works.

The find() call won't compile because you're passing it the wrong type to search for. map::find() expects its argument to be the same type as the map's key type, which is A*. You're passing a const A*, which is not implicitly convertible to an A* (but is comparable to an A*, which is why the handwritten search works). The implicit conversion only works in the other direction (A* to const A*, not const A* to A*).

Possibly you should be using const A* instead of A* as the map key; depending on what you're using the map for, this may or may not be practical. If you need the map key to be A*, you need to pass an A* to find(), which means either starting with an A* as your search target in the first place, or if you can only get it from its original source as a const A*, using find(const_cast<A*>(a)) to turn it into a pointer to non-const (which is not the same as a non-const pointer, a point that confuses a lot of C/C++ coders). Usually const_cast is inadvisable, but here it's safe since you're only comparing the pointer, not dereferencing it.

Ross Smith
Yes, this is an accurate expanded description of my problem. It seems that using a const_cast is the only way to go, but it's frustrating that no cast is needed with the "handwritten search". I am almost tempted to just use the handwritten search, since I hate casts. Could the original library find function have been written to work in this scenario, or is there a limitation in the C++ language?
bartsimpson
@bartsimpson - bad idea - member functions are preferable where they exist. Cast here is no big deal, just make it a `const_cast` not a C-style cast.
Steve Townsend
The big advantage of map::find() over a simple linear search is that it's much faster if the collection is large.
Ross Smith