Wie funktioniert `void_t`?

Ich habe Walter Browns Vortrag auf der Cppcon14 über moderne Template-Programmierung gesehen Part I, Teil I) wo er sein @ präsentiervoid_t SFINAE-Technik.

Beispiel
Gegeben eine einfache Variablenvorlage, die zu @ ausgewertet wivoid wenn alle Template-Argumente korrekt formuliert sind:

template< class ... > using void_t = void;

und das folgende Merkmal, das das Vorhandensein einer Mitgliedsvariablen mit dem Namen @ überprüMitglie:

template< class , class = void >
struct has_member : std::false_type
{ };

// specialized as has_member< T , void > or discarded (sfinae)
template< class T >
struct has_member< T , void_t< decltype( T::member ) > > : std::true_type
{ };

Ich habe versucht zu verstehen, warum und wie das funktioniert. Deshalb ein kleines Beispiel:

class A {
public:
    int member;
};

class B {
};

static_assert( has_member< A >::value , "A" );
static_assert( has_member< B >::value , "B" );

1. has_member< A >

has_member< A , void_t< decltype( A::member ) > >A::member existiertdecltype( A::member ) ist wohlgeformtvoid_t<> ist gültig und ergibtvoidhas_member< A , void > und wählt daher die spezialisierte Vorlagehas_member< T , void > und ergibttrue_type

2. has_member< B >

has_member< B , void_t< decltype( B::member ) > >B::member ist nicht vorhandedecltype( B::member ) ist schlecht geformt und versagt lautlos (sfinae)has_member< B , expression-sfinae > so wird diese Vorlage verworfencompiler findethas_member< B , class = void > mit void als Standardargumenthas_member< B > ergibtfalse_type

http: //ideone.com/HCTlB

Fragen
1. Ist mein Verständnis davon korrekt?
2. Walter Brown gibt an, dass das Standardargument genau der gleiche Typ sein muss wie das in @ verwendetvoid_t damit es funktioniert. Warum das? (Ich verstehe nicht, warum diese Typen übereinstimmen müssen. Tut der Job nicht einfach irgendeinen Standardtyp?)

Antworten auf die Frage(4)

Ihre Antwort auf die Frage