可以检测是否可以在类型上调用操作符或函数。要测试某个类是否具有的重载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>>;