2015-03-05 1 views
-1

Pourquoi n'imprime "B"std :: enable_if utilisant son type interne et sans l'utiliser

#include <iostream> 

template<typename T, typename U = void> 
struct Test 
{ static void apply() { std::cout << "A" << std::endl; } }; 

template<typename T> 
struct Test<T, typename std::enable_if<true>::type> 
{ static void apply() { std::cout << "B" << std::endl; } }; 

int main() 
{ 
    Test<int>::apply(); 
} 

mais celui-ci "A" ?:

#include <iostream> 

template<typename T, typename U = void> 
struct Test 
{ static void apply() { std::cout << "A" << std::endl; } }; 

template<typename T> 
struct Test<T, std::enable_if<true>> 
{ static void apply() { std::cout << "B" << std::endl; } }; 

int main() 
{ 
    Test<int>::apply(); 
} 

La seule différence entre eux est que, dans le premier, j'utilise typename std::enable_it<true>::type comme U (par exemple, void), mais dans la seconde, j'utilise directement std::enable_if<true> comme U, qui est également un type bien défini et sans plus de signification que void.

+4

'std :: enable_if ' a beaucoup plus de sens que 'void'. Il est un type qui a un type de membre nommé 'type' qui est égal à' void'. Donc 'void' et' std :: enable_if 'sont deux choses différentes (' void' n'a pas de membre 'type'),' typename std :: enable_if :: type' et 'void' ne le sont pas. – stefan

Répondre

4

Parce que quand vous écrivez Test<int> vous écrivez en fait Test<int, void> qui ne sera jamais le même que Test<int, std::enable_if<true>> (bien que ce soit la même chose que Test<int, typename std::enable_if<true>::type>)

2

Comme typename std::enable_if<true>::type est le même type que void, le premier extrait est équivalent à

template<typename T, typename U = void> 
struct Test 
{ static void apply() { std::cout << "A" << std::endl; } }; 

template<typename T> 
struct Test<T, void> // since typename std::enable_if<true>::type == void 
{ static void apply() { std::cout << "B" << std::endl; } }; 

Par conséquent, la deuxième définition est plus spécialisée, donc si vous ne fournissez deux arguments de modèle, celui-ci gagne en résolution de surcharge.

Cependant, dans le second exemple, vous il est juste une spécialisation pour la paire de types T et std::enable_if<true>, pas pour T et void. Cela peut être vérifié avec std::is_same<std::enable_if<true>, void>, qui évalue la valeur false (clairement, void n'a pas membre de type type, donc il ne peut pas être le même). Par conséquent, pour le deuxième extrait, la demande T<int> correspondra à T<int, void> pour laquelle une seule définition est pertinente, à savoir la première.