Como o `void_t` funciona
Eu assisti a palestra de Walter Brown no Cppcon14 sobre a programação de modelos modernos (Parte I, parte II) onde ele apresentou suavoid_t
Técnica SFINAE.
Exemplo:
Dado um modelo de variável simples que avalia comovoid
se todos os argumentos do modelo estiverem bem formados:
template< class ... > using void_t = void;
e a característica a seguir que verifica a existência de uma variável membro chamadamembro:
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
{ };
Tentei entender por que e como isso funciona. Portanto, um pequeno exemplo:
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
existedecltype( A::member )
é bem formadovoid_t<>
é válido e avalia comovoid
has_member< A , void >
e, portanto, escolhe o modelo especializadohas_member< T , void >
e avalia paratrue_type
2) has_member< B >
has_member< B , void_t< decltype( B::member ) > >
B::member
não existedecltype( B::member )
está mal formado e falha silenciosamente (sfinae)has_member< B , expression-sfinae >
então esse modelo é descartadocompilador encontrahas_member< B , class = void >
com void como argumento padrãohas_member< B >
avalia comofalse_type
Questões:
1. Minha compreensão disso está correta?
2. Walter Brown afirma que o argumento padrão deve ser exatamente o mesmo tipo que o usado emvoid_t
para que funcione. Por que é que? (Não vejo por que esses tipos precisam corresponder, apenas um tipo padrão não funciona?)