2009-09-20 7 views
3

Maintenant que nous savons que Concepts ne fait pas partie de C++ 0x, je cherche des méthodes pour imposer des restrictions sur les types dans les fonctions de template.Imposer des contraintes de types de fonctions de template, sans concepts C++ 0x

Voici deux exemples:

Si nous voulons nous assurer qu'un type donné est un entier, nous pouvons utiliser:

template <class N> inline int f(const N n) 
{ 
    if ((N)0.1 != 0)    // if type of N is floating-point 
     err() 

    .... 
} 

si nous voulons nous assurer qu'une donnée type est un entier non signé, nous pouvons utiliser:

template <class N> inline int f(const N n) 
{ 
    if ((N)-1 < (N)1)    // if type of N is floating-point/signed-integer 
     err() 

    .... 
} 

Je cherche des façons créatives t o vérifier s'il y a des restrictions supplémentaires, qui provoqueront un échec en phase d'exécution, ou mieux, à la compilation (sans concepts et sans RTTI).

Des suggestions?

Répondre

12

Vos vérifications peuvent être traitées beaucoup mieux au moment de la compilation en utilisant des caractères de type.

La première:

STATIC_ASSERT(std::numeric_limits<N>::is_integer) 

La seconde:

STATIC_ASSERT(not std::numeric_limits<M>::is_signed) 

Jetez un oeil à la Boost Concept Check Library et à Boost.StaticAssert.

2

Vous pouvez approximer les modèles de fonctions restreintes via SFINAE étendu. Voici un exemple qui compile en fait avec GCC 4.4.1 en mode C++ 0x:

#include <iostream> 
#include <type_traits> 

#define REQUIRES(...) ,class=typename std::enable_if<(__VA_ARGS__)>::type 

template <typename IntType 
    REQUIRES(std::is_integral<IntType>::value) 
> 
inline IntType f(IntType n) { 
    return n; 
} 

int main() { 
    std::cout << f(2) << '\n'; 
    // std::cout << f(3.1415) << '\n'; // won't work 
} 

La bonne chose à propos SFINAE est que lorsque la déduction de l'argument de modèle échoue, le modèle de fonction est simplement ignoré et ne sera pas une partie de l'ensemble de surcharge. L'exemple ci-dessus exploite le fait que C++ 0x va prendre en charge les arguments de modèle par défaut pour les modèles de fonctions. En bon vieux 98 C++, il ressemblerait à ceci:

template <typename IntType> 
inline 
typename boost::enable_if_c<(
    std::numeric_limits<IntType>::is_integer 
),IntType>::type f(IntType n) { 
    return n; 
} 

Cheers, S

0

Pour vérifier facilement l'héritage, vous pouvez également faire

template <typename T> 
class MyClass 
{ 
private: 
    static ClassA *checkIfTIsA() { return (T *)NULL; } 
}; 
Questions connexes