c ++ map

时间:2015-08-17 17:35:19

标签: c++ templates

我想保存一些重复的工作并编写一个模仿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")

,函数正常工作

如何正确地做到这一点?

3 个答案:

答案 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();
}

DEMO

您现在不需要明确指定类型模板参数。

准确地说,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