tags:

views:

256

answers:

7

My use case:

map<string, Car> cars;
bool exists(const string& name) {
  // somehow I should find whether my MAP has a car
  // with the name provided
  return false;
} 

Could you please suggest the best and the most elegant way to do it in C++? Thanks.

+3  A: 
bool exists(const string& name)
{
    return cars.find(name) != cars.end();
}
Mike Seymour
Make the function `const` if it's a member?
Nikolai N Fetissov
If it's a member, then yes.
Mike Seymour
+19  A: 
return cars.find(name) != cars.end();
KennyTM
+5  A: 

Sure, use an iterator

map<string,Car>::const_iterator it = cars.find(name);
return it!=cars.end();
Tom
Since you're not mutating `cars`, it's better to get a `const_iterator`.
KennyTM
good point. Editing....
Tom
But if `cars` isn't const, `cars.find(name)` will return an `iterator` that has to be converted to a `const_iterator` and `cars.end()` will return an `iterator` which will then be converted to a `const_iterator` when compared to `it`. Why fight it; why not just use an `iterator` ?
Charles Bailey
Why not skip the temporary and not worry about it: `cars.find(name) != cars.end()`?
D.Shawley
@ D. Shwaley To illustrate.
Tom
+1  A: 
bool exists(const std::map<std::string, Car>& cars, const std::string& name) {
  return cars.end() != cars.find(name);
}
Rudi
Why not make it even more generic by making it a template function? But it probably won't fulfill the requirement of elegance any better..
mxp
@mxp, see my solution for that (http://stackoverflow.com/questions/2781899/how-to-find-whether-an-element-exists-in-stdmap/2782084#2782084).
D.Shawley
+1  A: 

std::map::find(const key_type& x );

It returns map::end if the item doesn't exist.

Brian Roach
+8  A: 

You could also use

bool exists(const string& name) {
  return cars.count(name) != 0;
} 
Johannes Schaub - litb
`!= 0` optional.
Potatoswatter
@Potatoswatter But makes it clear exactly what is being tested. Its purely a stylistic issue, but I tend not to rely on implicit int to bool conversions.
KeithB
@Potatoswatter: The explicit comparison would suppress a VC++ warning ("performance warning: forcing integer to bool") ;)
UncleBens
+4  A: 

What about:

template <typename KeyType, typename Collection>
bool exists_in(Collection const& haystack, KeyType const& needle) {
    return std::find(haystack.begin(), haystack.end(), needle) != haystack.end();
}

template <typename K, typename V>
bool exists_in(std::map<K,V> const& haystack, K const& needle) {
    return haystack.find(needle) != haystack.end();
}

This makes exists_in work with any standard container via std::find and use a special version for std::map since it offers a more efficient searching alternative. You could add additional specializations as necessary (e.g., for std::set and others).

D.Shawley
Pass everything by const reference.
UncleBens