Prenons l'exemple suivant:Comment puis-je écrire un modèle de fonction pour tous les types avec un trait de type particulier?
struct Scanner
{
template <typename T>
T get();
};
template <>
string Scanner::get()
{
return string("string");
}
template <>
int Scanner::get()
{
return 10;
}
int main()
{
Scanner scanner;
string s = scanner.get<string>();
int i = scanner.get<int>();
}
La classe Scanner
est utilisé pour extraire des jetons d'une source. Le code ci-dessus fonctionne très bien, mais échoue lorsque j'essaie d'autres types intégraux comme un char
ou un unsigned int
. Le code pour lire ces types est exactement le même que le code pour lire un int
. Je pourrais juste dupliquer le code pour tous les autres types intégraux que j'aimerais lire, mais je préfèrerais définir un modèle de fonction pour tous les types entiers.
J'ai essayé ce qui suit:
struct Scanner
{
template <typename T>
typename enable_if<boost::is_integral<T>, T>::type get();
};
Ce qui fonctionne comme un charme, mais je ne suis pas sûr comment obtenir Scanner::get<string>()
à fonctionner à nouveau. Alors, comment puis-je écrire du code afin que je puisse faire scanner.get<string>()
et scanner.get<any integral type>()
et avoir une seule définition pour lire tous les types intégrales?
Mise à jour: question de bonus: Que se passe-t-il si je veux accepter plus d'une plage de classes en fonction de certains traits? Par exemple: comment dois-je aborder ce problème si je veux avoir trois fonctions get
acceptant (i) des types entiers (ii) des types à virgule flottante (iii), respectivement.
Je remarquerais que vous pourriez probablement utiliser les commandes boost :: mpl :: and_ et boost :: mpl :: or_ pour combiner les arguments de 'disable_if'. +1 néanmoins :) –
Vous pouvez également utiliser 'ice_and' et' ice_or' de la bibliothèque Boost. –