我想保存一些重复的工作,并编写一个模仿Java .containsKey()方法的函数.
基本上我想要这样的东西:
using namespace std;
map<string,XYclass> mymap;
if (!contains(mymap,"key as string") ) cout << "key not found" << endl;
Run Code Online (Sandbox Code Playgroud)
在C++中,如果地图包含以下方式的键,则可以检查:
m.find(str) != m.end();
Run Code Online (Sandbox Code Playgroud)
我想写一个泛型方法,如果一个键包含在一个映射中,它返回true.
到目前为止我有以下内容:
template<typename A, typename B> inline bool contains(const std::map< A, B > m, const A& str)
{
return m.find(str) != m.end();
}
Run Code Online (Sandbox Code Playgroud)
当我在map<string,int>跟随调用的情况下运行它时,将无法进行模板参数推导,contains(mymap,"key as string")因为"key as string"实际上是一个char数组.
当我进行显式实例化时(即通过使用以下调用contains<string,int>(mymap,"key as string")),函数工作正常
怎么做得好?
可以使用以下标识技巧从模板参数推导中排除参数:
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();
}
Run Code Online (Sandbox Code Playgroud)
您现在不需要显式指定类型模板参数.
确切地说,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);
Run Code Online (Sandbox Code Playgroud)
不要将其硬编码为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(); }
Run Code Online (Sandbox Code Playgroud)
decltype如果您需要其他重载,说明符将执行 SFINAE 。