#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 ?
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.
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.