I want to save some repeating work and write a function that mimicks Java .containsKey() method.
Basically I would like to have something like this:
using namespace std;
map<string,XYclass> mymap;
if (!contains(mymap,"key as string") ) cout << "key not found" << endl;
In C++ one can check, if a map contains key in following way:
m.find(str) != m.end();
I want to write a generic method that returns true if a key is contained in a map.
So far I have following:
template<typename A, typename B> inline bool contains(const std::map< A, B > m, const A& str)
{
return m.find(str) != m.end();
}
which will fail to do template argument deduction, when I run it on a map<string,int>
with following call contains(mymap,"key as string")
, as "key as string" is actually a char array.
Function works fine when I do explicit instantiation (i.e. by using following call contains<string,int>(mymap,"key as string")
)
How to do it properly?
keySet() method in Java is used to create a set out of the key elements contained in the hash map. It basically returns a set view of the keys or we can create a new set and store the key elements in them. Parameters: The method does not take any parameter.
get(Object) does explicitly warn about the subtle differences between Map. get(Object) and Map. containsKey(Object) : If this map permits null values, then a return value of null does not necessarily indicate that the map contains no mapping for the key; it's also possible that the map explicitly maps the key to null .
The time complexity of containsKey has changed in JDK-1.8, as others mentioned it is O(1) in ideal cases.
HashMap. get() method of HashMap class is used to retrieve or fetch the value mapped by a particular key mentioned in the parameter. It returns NULL when the map contains no such mapping for the key.
One can exclude parameters from template argument deduction with the below identity trick:
template <typename T>
struct identity { typedef T type; };
template <typename A, typename B>
inline bool contains(const std::map<A, B>& m
, const typename identity<A>::type& str)
{
return m.find(str) != m.end();
}
DEMO
You don't need to specify type template arguments explicitly now.
To be precise, std::map
has the total of four type template parameters:
template <typename A, typename B, typename Cmp, typename Alloc>
inline bool contains(const std::map<A, B, Cmp, Alloc>& m
, const typename identity<A>::type& str);
Don't hard-code it to std::map
. The expression c.find( k ) != c.end()
will work for any container with a find
method returning an iterator. The function is applicable to any such types.
As others have noted, std::map
has additional template parameters for the comparison function and the node allocator. In principle, listing all its parameters violates the separation of concerns.
template< typename container, typename key >
auto contains( container const & c, key const & k )
-> decltype( c.find( k ) != c.end() )
{ return c.find( k ) != c.end(); }
The decltype
specifier performs SFINAE, in case you want other overloads.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With