檢測表示式是否有效
可以檢測是否可以在型別上呼叫操作符或函式。要測試一個類是否具有 std::hash
的過載,可以執行以下操作:
#include <functional> // for std::hash
#include <type_traits> // for std::false_type and std::true_type
#include <utility> // for 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
{};
Version >= C++ 17
從 C++ 17 開始,std::void_t
可用於簡化這種型別的構造
#include <functional> // for std::hash
#include <type_traits> // for std::false_type, std::true_type, std::void_t
#include <utility> // for 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
{};
如果 T
對 std::hash
有超載,這些可用於使用 std::unordered_map<T>
,但是否則嘗試使用 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>>;