4

I have the following template function:

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

The keys in the map are not const.

Now, I may have a const K. How can I write a template that would allow me to pass in both K andconst K` to the function?

Is the solution to use a const_cast every time I call the function?

Rakete1111
  • 47,013
  • 16
  • 123
  • 162
chrise
  • 4,039
  • 3
  • 39
  • 74

2 Answers2

7

You can achieve what you want with the following

template <typename Key, typename Value, typename K>
bool hasKey(const std::map<Key, Value>& mp, const K& k) {
    return mp.find(k) != mp.end();
}

This way you are sure when looking at the declaration of the function that neither operand is going to be modified since they are both references to const.

Both non-const and const references (and even rvalues) to key types can be passed to the .find() methods in std::map. This works because the .find() method accepts a key type by const reference, so if you pass a non-const reference it gets bound by a const reference anyway, so it doesn't make a difference.

Another thing that you get from templating the key types separately is compatibility with transparent comparators (since C++14, see http://en.cppreference.com/w/cpp/container/map/find). For more on what transparent comparators are see What are transparent comparators?.

Curious
  • 20,870
  • 8
  • 61
  • 146
3

You could have hasKey based on a concept of Map:

template<typename Map>
bool hasKey(const Map& m, const typename Map::key_type& k) {
    return m.find(k) != m.end();
} 
Cosme
  • 191
  • 2
  • 6