Search code examples
c++c++17template-meta-programmingsfinae

std::void_t vs customize function in SFINAE usage


#include <iostream>

template <typename T>
struct CheckX
{
    using TypeOfX = decltype(T::x);
    using Value = void;
};

struct A
{
};

struct B
{
    int x;
};

template <typename T , typename = void>
struct Res
{
    static constexpr bool value = false;
};

// template <typename T>
// struct Res<T , std::void_t<decltype(T::x)>>
// {
//     static constexpr bool value = true;
// };

template <typename T>
struct Res<T , typename CheckX<T>::Value>
{
    static constexpr bool value = true;
};

int main()
{
    std::cout << Res<B>::value << '\n'; 
    std::cout << Res<A>::value << '\n'; 
}

These is the code that I want to implement a checker which check if a member x exist in a struct.
I notice that the usage of the customize CheckX result in a compilation fail while std library std::void_t will do the work.
What I am missing here ?


Solution

  • The problem is that the given using declaration inside CheckX is not in the immediate context which is the only place where/when SFINAE will work.

    Solution

    Just put the using declaration in the immediate context by changing the using declaration to a alias template as shown below:

    template <typename T>
    struct CheckX
    {
        template<typename U = T>
        using TypeOfX = decltype(U::x);
        using Value = void;
    };
    

    Program works now.


    See also What is immediate context in SFINAE which explains the basics and my answer gives a workaround.