使用以下has_member函数,SFINAE无法正常工作?

Nat*_*mal 8 c++ templates sfinae template-specialization c++11

我正在尝试Walter Brown的TMP演讲中的例子,我正在尝试让他的has_member实现工作.

然而,实现似乎错误地返回true,这使我相信有一些我不理解的SFINAE的细节.

#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;                                                                                                                 
}      
Run Code Online (Sandbox Code Playgroud)

输出是:

Does FooWithType have type member? YES
Does FooNoType have type member? YES
Run Code Online (Sandbox Code Playgroud)

我在Ubuntu上的gcc 4.8.2.

eca*_*mur 11

问题是gcc 4.8.2(和gcc 5.0之前的版本)不认为别名模板中的未使用参数适合SFINAE.解决方法是转发到voider类模板:

template <class ... T> struct voider { using type = void; };
template <class ... T>
using void_t = typename voider<T...>::type;
Run Code Online (Sandbox Code Playgroud)

来自http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3911.pdf第2.3节:

唉,我们在使用上面非常简单的定义时遇到了实现差异(Clang vs. GCC).我们(继续)推测这是因为CWG问题1558:"14.5.7 [temp.alias]的当前措辞没有指定别名模板特化中未使用的参数的处理."