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 ergibtvoid
has_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
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?)