通過創建一個模板元函數來檢查一個類是否有一個特定的成員。以下是一個例子:
#include <type_traits>template<typename T, typename = void>
struct has_type_member : std::false_type {};template<typename T>
struct has_type_member<T,
std::void_t<typename T::type>> : std::true_type {};struct Test {using type = double;
};int main() {static_assert(has_type_member<Test>::value, "Test::type exists");static_assert(!has_type_member<int>::value, "int::type doesn't exist");return 0;
}
在這個例子中,has_type_member
是一個模板元函數,它檢查其模板參數 T
是否有一個名為 type
的成員。它首先假設 T
沒有 type
成員,然后通過模板特化來檢查 T
是否真的有 type
成員。
如果 T::type
存在,那么 std::void_t<typename T::type>
就是 void
,所以 has_type_member<T, std::void_t<typename T::type>>
就是 has_type_member<T, void>
,這匹配了模板特化,所以 has_type_member<T>::value
是 true
。
如果 T::type
不存在,那么 std::void_t<typename T::type>
就會導致一個編譯錯誤,但是由于模板參數的 SFINAE(Substitution Failure Is Not An Error)特性,這個錯誤會被忽略,然后編譯器就會選擇 has_type_member<T, void>
的主模板,所以 has_type_member<T>::value
是 false
。
所以,你可以使用 has_type_member<T>::value
來檢查一個類型 T
是否有一個 type
成員。
擴展:
SFINAE 是 “Substitution Failure Is Not An Error” 的縮寫,它是 C++ 模板元編程中的一個重要概念。
在模板實例化過程中,編譯器會嘗試用具體的類型替換模板參數。這個替換過程有時可能會失敗,例如當我們嘗試調用一個不存在的函數或訪問一個不存在的成員。在大多數情況下,這種替換失敗將導致編譯錯誤。但在某些情況下,C++ 標準允許這種替換失敗,并且不會產生編譯錯誤,這就是 SFINAE 的原理。