Comment `void_t travail

J'ai regardé Walter Brown parler à Cppcon14 moderne modèle de programmation (Partie I, Partie II) où il a présenté son void_t SFINAE technique.

Exemple:

Étant donné une variable simple modèle qui donne void si tous les arguments de modèle sont bien formés:

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

et suivants trait de caractère qui vérifie l'existence d'une variable membre appelé membre:

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
{ };

J'ai essayé de comprendre pourquoi et comment cela fonctionne. Donc un petit exemple:

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 existe
    • decltype( A::member ) est bien formé
    • void_t<> est valide et évalue à void
  • has_member< A , void > et, par conséquent, il choisit spécialisées modèle
  • has_member< T , void > et évalue à true_type

2. has_member< B >

  • has_member< B , void_t< decltype( B::member ) > >
    • B::member n'existe pas
    • decltype( B::member ) est mal formé et échoue silencieusement (sfinae)
    • has_member< B , expression-sfinae > donc ce modèle est jeté
  • compilateur trouve has_member< B , class = void > avec le vide comme argument par défaut
  • has_member< B > évalue à false_type

http://ideone.com/HCTlBb

Questions:

1. Est ma compréhension de ce correct?

2. Walter Brown affirme que l'argument par défaut doit être exactement du même type que celui utilisé dans void_t pour que cela fonctionne. Pourquoi est-ce? (Je ne vois pas pourquoi ces types doivent correspondre, n'est-ce pas un défaut, le type fait le travail?)

  • Ad 2) Imaginez la statique affirmer a été écrit comme: has_member<A,int>::value. Ensuite, la spécialisation partielle qui donne has_member<A,void> ne peut pas correspondre. Par conséquent, il doit être has_member<A,void>::value, ou, avec du sucre syntaxique, un argument par défaut de type void.
  • Merci, je vais modifier cela. Mh, je ne vois pas la nécessité d'en avoir has_member< T , class = void > défaut dans void encore. En supposant que ce trait de caractère sera utilisé uniquement avec 1 argument de modèle à tout moment, la valeur par défaut de l'argument pourrait être n'importe quel type?
  • Question intéressante.
  • Notez que Dans cette proposition, open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4436.pdf, Walter changé template <class, class = void> à template <class, class = void_t<>>. Alors maintenant, nous sommes libres de faire ce que nous voulons void_t alias implémentation du modèle 🙂
InformationsquelleAutor nonsensation | 2014-12-29