Bonjour à tous,

J'ai vu que beaucoup de classes de type_traits suivaient l'idée d'une classe A héritant de B, et de spécialisations de classe A héritant de C (B et C étant boost::true_type et boost::false_type, et A étant par exemple is_integer).
L'idée étant de définir, dans une fonction générique FONC<T>, un appel à la fonction CALL( A<T> ), qui invoque l'une des deux surcharges CALL( B ) ou CALL( C ) selon la valeur de T. On trouve un exemple ici.
Pour clarifier, j'ai le sentiment que l'idée générale est de faire :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include	<iostream>
 
struct True {};
struct False {};
 
template <class T> struct IsInt : public False {};
template <> struct IsInt <int> : public True {};
 
void Fonc( False const& )
{ std::cout << "Is not signed int\n"; }		
void Fonc( True const& )
{ std::cout << "Is signed int\n"; }		
 
template <class T>
void Do( void )
{ Fonc( IsInt<T>() ); }
Ma question est : je suis géné par le fait d'utiliser une surcharge "classique" par paramètre, où une spécialisation de template suffirait. Il suffirait alors de définir A::type (comme le fait add_const, etc.) en fonction du template de A, et d'invoquer CALL<A::type>() au lieu de CALL( A::type() ). Pour être plus clair, cela voudrait dire faire :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include	<iostream>
 
struct True {};
struct False {};
 
template <class T> struct IsInt
{ typedef False type; };
template <> struct IsInt <int> 
{ typedef True type; };
 
template <class T>
void Fonc( void )
{ std::cout << "Is not signed int\n"; }		
template <>
void Fonc<True>( void )
{ std::cout << "Is signed int\n"; }		
 
template <class T>
void Do( void )
{ Fonc<typename IsInt<T>::type>(); }
Cela me semble plus correct, et ça m'a l'air aussi plus performant : j'ai regardé les instructions ASM générées par g++ -O2, et le premier bout de code passe un argument à Fonc(), même si cet argument n'est pas utilisé (-> il rajoute une instruction "lea ...").
Mais j'aimerais avoir votre idée sur la question :
- qu'en pensez-vous ?
- est-il possible d'éviter une surcharge paramétrique dans un tel cas avec boost::is_integer ou struct similaire ?

Merci beaucoup

Edit : je viens de penser à cette autre solution :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include	<iostream>
#include	<boost/type_traits.hpp>
 
template <class T> struct IsInt : public boost::false_type {};
template <> struct IsInt <int> : public boost::true_type {};
 
template <bool>
void Fonc( void )
{ std::cout << "Is not signed int\n"; }		
template <>
void Fonc<true>( void )
{ std::cout << "Is signed int\n"; }		
 
template <class T>
void Do( void )
{ Fonc<IsInt<T>::value>(); }