I'm trying out examples from Walter Brown's TMP talk and I'm trying to get his has_member
implementation working.
However the implementation seems to falsely return true which leads me to believe there is some detail of SFINAE that I am not understanding.
#include <iostream>
#include <type_traits>
template <class ...>
using void_t = void;
template <class, class = void>
struct has_type_member: std::false_type {};
template <class T>
struct has_type_member<T, void_t<typename T::type> >: std::true_type {};
struct FooWithType
{
typedef int type;
};
struct FooNoType
{
};
int main()
{
std::cout << "Does FooWithType have type member? " <<
(has_type_member<FooWithType>() ? "YES" : "NO") << "\n";
std::cout << "Does FooNoType have type member? " <<
(has_type_member<FooNoType>() ? "YES" : "NO") << "\n";
return 1;
}
Output is:
Does FooWithType have type member? YES
Does FooNoType have type member? YES
I am on gcc 4.8.2 on Ubuntu.
The problem is that gcc 4.8.2 (and prior to gcc 5.0) does not regard unused arguments in alias templates as suitable for SFINAE. The workaround is to forward to a
voider
class template:From http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3911.pdf section 2.3: