我想保存一些重复的工作并编写一个模仿Java的函数 .containsKey()方法。
基本上我想要这样的东西:
using namespace std;
map<string,XYclass> mymap;
if (!contains(mymap,"key as string") ) cout << "key not found" << endl;
在C ++中,如果地图包含以下方式的密钥,则可以检查:
m.find(str) != m.end();
我想写一个泛型方法,如果一个键包含在地图中,则返回true。
到目前为止,我有以下内容:
template<typename A, typename B> inline bool contains(const std::map< A, B > m, const A& str)
{
return m.find(str) != m.end();
}
当我在map<string,int>
上运行跟随调用contains(mymap,"key as string")
时,将无法进行模板参数推断,因为“key as string”实际上是一个char数组。
当我进行显式实例化时(即通过使用以下调用contains<string,int>(mymap,"key as string")
)
如何正确地做到这一点?
答案 0 :(得分:6)
可以使用以下标识技巧从模板参数推导中排除参数:
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();
}
您现在不需要明确指定类型模板参数。
准确地说,std::map
总共包含四个类型模板参数:
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);
答案 1 :(得分:3)
不要将其硬编码到std::map
。表达式c.find( k ) != c.end()
适用于任何返回迭代器的find
方法的容器。该功能适用于任何此类类型。
正如其他人所说,std::map
为比较函数和节点分配器提供了额外的模板参数。原则上,列出其所有参数违反了关注点的分离。
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(); }
decltype
说明符执行SFINAE,以防您想要其他重载。
答案 2 :(得分:2)
我会使用3个参数声明contains()
函数作为模板:
template<typename Key, typename Value, typename Arg>
inline bool map_contains(const std::map< Key, Value > m, const Arg& value)
{
return m.find(value) != m.end();
}
注意,现在Arg
必须隐式转换为Key
。您可以轻松删除此要求 - 您只需在find()
显式转换为value
类型的情况下调用Key
。
现场演示:click。