2023年1月10日 星期二

C++:如何應用 SFINAE 實作 type trait

以下為一個 SFINAE 的 type trait 例子,用來判斷一個型態是否有 default constructor。如果有 default constructor 的話那 typename = decltype(U()) 就能被替換,否則就會產生一個 substitution failure,但由於 test(…) 是 fallback,所以整段程式仍然能夠編譯。

#include <iostream>
#include <typeinfo>
#include <type_traits>

template <typename T>
struct IsDefaultConstructibleHelper {
private:
    template<typename U, typename = decltype(U())>
        static std::true_type test(void*);
    template<typename>
        static std::false_type test(...);
public:
    using Type = decltype(test<T>(nullptr));
};

template <typename T>
struct IsDefaultConstructibleT : IsDefaultConstructibleHelper<T>::Type
{};

struct S {
  S() = delete;  
};

int main()
{
    // true
    std::cout << std::boolalpha << IsDefaultConstructibleT<int>::value << std::endl;
    // false
    std::cout << std::boolalpha << IsDefaultConstructibleT<S>::value << std::endl; 
    return 0;
}