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

从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>>;