SFINAE几种实现方式


一、通过函数返回值实现

template<class T>
typename std::enable_if::value>::type 
    construct(T*) 
{
    std::cout << "default constructing trivially default constructible T\n";
}
template<class T, class... Args>
std::enable_if_t::value> // Using helper type
    construct(T* p, Args&&... args) 
{
    std::cout << "constructing T with operation\n";
    ::new(detail::voidify(p)) T(static_cast(args)...);
}
template
auto len (T const& t) -> decltype( (void)(t.size()), T::size_type() ) {
    return t.size();
}

二、通过函数参数实现

template<class T>
void destroy(
    T*, 
    typename std::enable_if<
        std::is_trivially_destructible::value
    >::type* = 0
){
    std::cout << "destroying trivially destructible T\n";
}

三、通过模板非类型参数实现

template<class T,
         typename std::enable_if<
             !std::is_trivially_destructible{} &&
             (std::is_class{} || std::is_union{}),
            bool>::type = true>
void destroy(T* t)
{
    std::cout << "destroying non-trivially destructible T\n";
    t->~T();
}

四、通过模板类型参数实现

template<class T,
    typename = std::enable_if_t::value> >
void destroy(T* t) // note: function signature is unmodified
{
    for(std::size_t i = 0; i < std::extent::value; ++i) {
        destroy((*t)[i]);
    }
}

 当有多个重载时,不推荐使用该方式,会在C++语义上出现冲突,宜使用方法三。

五、通过模板偏特化实现

template void>
struct iterator_trait
: std::iterator_traits {};
 
template 
struct iterator_trait>
: std::iterator_traits {};

六、通过c++20的concept实现

template
requires std::is_convertible_vstring>
Person(STR&& n) : name(std::forward(n)) {
...
}
template
concept ConvertibleToString = std::is_convertible_vstring>;

...
template
requires ConvertibleToString
Person(STR&& n) : name(std::forward(n)) {
...
}
template
Person(STR&& n) : name(std::forward(n)) {
...
}