Comment puis-je écrire un modèle de fonction pour tous les types avec un trait de type particulier?

StackOverflow https://stackoverflow.com/questions/2537229

  •  22-09-2019
  •  | 
  •  

Question

Prenons l'exemple suivant:

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 je tente de get autres types entiers 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 pouvais dupliquer le code pour tous les autres types entiers que je voudrais lire, mais je préfère définir un modèle de fonction pour tous les types entiers.

Je l'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 pour que je puisse faire scanner.get<string>() et scanner.get<any integral type>() et ont une définition unique de lire tous les types entiers?

Mise à jour: question bonus : si je veux accepter plus d'une gamme de classes en fonction de certains traits? Par exemple: comment dois-je aborder ce problème si je veux avoir trois fonctions get qui acceptent (i) les types intégraux (ii) flottants types de point (iii) chaînes, respectivement

.
Était-ce utile?

La solution

struct Scanner
{
    template <typename T>
    typename boost::enable_if<boost::is_integral<T>, T>::type get()
    {
        return 10;
    }
    template <typename T>
    typename boost::disable_if<boost::is_integral<T>, std::string>::type get()
    {
        return "string";
    }
};

Mise à jour "si je veux accepter plus d'une gamme de classes en fonction de certains traits?"

struct Scanner
{
    template <typename T>
    typename boost::enable_if<boost::is_integral<T>, T>::type get()
    {
        return 10;
    }

    template <typename T>
    typename boost::enable_if<boost::is_floating_point<T>, T>::type get()
    {
        return 11.5;
    }

    template <typename T>
    std::string get(
          typename boost::disable_if<boost::is_floating_point<T>, T>::type* = 0, 
          typename boost::disable_if<boost::is_integral<T>, T>::type* = 0)

    {
        return std::string("string");
    }
};

Autres conseils

à un autre modèle Defer. Voici le schéma général pour ce que vous voulez:

template <typename T, bool HasTrait = false>
struct scanner_impl;

template <typename T>
struct scanner_impl
{
    // Implement as though the trait is false
};

template <typename T>
struct scanner_impl<true>
{
    // Implement as though the trait is true
};

// This is the one the user uses
template <typename T>
struct scanner : scanner_impl<T, typename has_my_trait<T>::value>
{
};
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top