Wie kann ich eine Funktionsvorlage für alle Typen mit einem bestimmten Typ Merkmale schreiben?

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

  •  22-09-2019
  •  | 
  •  

Frage

Betrachten Sie das folgende Beispiel:

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>();
}

Die Scanner Klasse wird verwendet, Token von einer Quelle zu extrahieren. Der obige Code funktioniert gut, aber nicht, wenn ich versuche andere integrale Typen get wie ein char oder eine unsigned int. Der Code dieser Art zu lesen ist genau der gleiche wie der Code eine int zu lesen. Ich konnte nur den Code für alle anderen ganzzahligen Typen duplizieren ich lesen möchte, aber ich würde lieber für alle ganzzahligen Typen ein Funktions-Template definieren.

Ich habe versucht, die folgenden:

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

Welche funktioniert wie ein Charme, aber ich bin nicht sicher, wie wieder Scanner::get<string>() auf Funktion zu erhalten. Also, wie kann ich Code schreiben, so dass ich scanner.get<string>() und scanner.get<any integral type>() tun können, und haben eine einheitliche Definition alle ganzzahligen Typen zu lesen?

Update: Bonus-Frage : Was passiert, wenn ich will mehr als eine Reihe von Klassen akzeptieren, basierend auf einigen Zügen? Zum Beispiel: Wie soll ich dieses Problem nähern, wenn ich will drei get Funktionen haben, die accept (i) ganzzahlige Typen (ii) Punkttypen (iii) Strings schwebenden bzw.

.
War es hilfreich?

Lösung

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";
    }
};

Update „Was passiert, wenn ich mehr als eine Reihe von Klassen auf einigen Zügen auf Basis akzeptieren will?“

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");
    }
};

Andere Tipps

Aufschieben auf eine andere Vorlage. Hier ist das allgemeine Muster für das, was Sie wollen:

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>
{
};
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top