可以检测是否可以在类型上调用操作符或函数。要测试某个类是否具有的重载std::hash,可以执行以下操作:
#include <functional> // 对于std :: hash #include <type_traits> // 对于std :: false_type和std :: true_type #include <utility> // 对于std :: declval template<class, class = void> struct has_hash : std::false_type {}; template<class T> struct has_hash<T, decltype(std::hash<T>()(std::declval<T>()), void())> : std::true_type {};
从C ++ 17开始,std::void_t可用于简化此类构造
#include <functional> // 对于std :: hash #include <type_traits> // 对于std :: false_type,std :: true_type,std :: void_t #include <utility> // 对于std :: declval template<class, class = std::void_t<> > struct has_hash : std::false_type {}; template<class T> struct has_hash<T, std::void_t< decltype(std::hash<T>()(std::declval<T>())) > > : std::true_type {};
其中std::void_t定义为:
template< class... > using void_t = void;
为了检测是否operator<定义了诸如的运算符,其语法几乎相同:
template<class, class = void> struct has_less_than : std::false_type {}; template<class T> struct has_less_than<T, decltype(std::declval<T>() < std::declval<T>(), void())> : std::true_type {};
这些可用于对std::unordered_map<T>ifT进行重载的if std::hash,否则尝试使用a std::map<T>:
template <class K, class V> using hash_invariant_map = std::conditional_t< has_hash<K>::value, std::unordered_map<K, V>, std::map<K,V>>;