C++ 检测表达式是否有效
示例
可以检测是否可以在类型上调用操作符或函数。要测试某个类是否具有的重载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进行重载的ifstd::hash,否则尝试使用astd::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>>;