2015-05-18 9 views
5

Ich verstehe das Grundkonzept der Verwendung der rekursiven Natur der variadischen Template-Parameter und einer spezifischen Template-Instanziierung, um den Pfad durch die Parameterliste nacheinander zu "essen".Was brauche ich noch, um variadische Template-Vererbung zum Erzeugen von Lambda-Überladungen zu verwenden?

Ich verstehe, dass lambdas geschrieben werden kann, um bestimmte Typen zu nehmen und dann bestimmte Typen zurückgeben. Denken Sie daran, dass ich immer noch C++ 14 und C++ 11 lerne, also habe ich das eine oder andere nicht gemeistert.

Hier war mein Versuch, nachdem bei otherStack Overflow questions bei der Suche:

// For std::string 
#include <string> 

// For std::cout 
#include <iostream> 


//Create a generalized list instantiation 
template <typename ... F> 
struct overload : public F... { 
    overload(F... f) : F(f)... {} 
};  

//Create an specific end-case, where we directly 
//inherit the() operator in order to inherit 
//multiple() overloads 
template <typename F> 
struct overload : F { 
    using F::operator(); 
}; 


//template function to create an overload 
template <class... F> 
auto make_overload(F... f) { 
    return (f...); 
} 

int main() { 
    auto f = [](int x,int y) -> int { 
     return x+y; 
    }; 
    auto g = [](double x,double y) -> int { 
     return std::ftoi(x+y); 
    }; 
    auto h = [](std::string x,std::string y) -> int { 
     return std::stoi(x+y); 
    }; 

    //Ah, but this is a function. 
    auto fgh = make_overload(f,g,h); 

    std::cout << (fgh(1,2)) << std::endl; 
    std::cout << (fgh(1.5,2.5)) << std::endl; 
    std::cout << (fgh("bob","larry")) << std::endl; 
} 

Coliru: http://coliru.stacked-crooked.com/a/5df2919ccf9e99a6

Was soll ich hier konzeptionell fehlt? Andere Antworten könnten dieses Problem auf den ersten Blick prägnant beantworten, aber ich suche nach einer Erklärung, warum die Antwort meinem Denken entgeht. Wenn ich verstehe, dass ich using F::operator() tun muss, um die Operatoren zu erben, und ich richtig feststelle, dass die Rückgabe- und Parametertypen unterschiedlich sind, was muss ich noch tun, damit dies funktioniert?

Hier ist mein Gedankengang:

  1. Erstellen Sie eine allgemeine variadische Vorlage Basisklasse.
  2. Erstellen Sie einen spezifischen Vorlagenfall, um einen spezifischen Lambdas operator() zu überlasten.
  3. Erstellen Sie eine Hilfsfunktion, um eine Variant-Vorlage-Argumentliste zu erstellen, und verwenden Sie sie dann, um die Klasse "Überladung" zu erstellen.
  4. Stellen Sie sicher, dass die Typen eindeutig sind.
+0

Beachten Sie, dass Sie (teilweise) Spezialisierung verwenden müssen, wenn Sie Struktur verwenden, können Sie * Strukturen * nicht überladen. – Jarod42

Antwort

4

Sie haben nicht tatsächlich recurse.

// primary template; not defined. 
template <class... F> struct overload; 

// recursive case; inherit from the first and overload<rest...> 
template<class F1, class... F> 
struct overload<F1, F...> : F1, overload<F...> { 
    overload(F1 f1, F... f) : F1(f1), overload<F...>(f...) {} 

    // bring all operator()s from the bases into the derived class 
    using F1::operator(); 
    using overload<F...>::operator(); 
};  

// Base case of recursion 
template <class F> 
struct overload<F> : F { 
    overload(F f) : F(f) {} 
    using F::operator(); 
}; 
+0

Es scheint, dass [dies nicht kompiliert] (http://coliru.stacked-crooked.com/a/1466751cf8c81195). – VermillionAzure

+1

@VermillionAzure: Es [kompiliert] (http://coliru.stacked-crooked.com/a/f1273aa625818808) mit Tippfehler behoben – Jarod42

+0

@ Jarod42 Vielen Dank! Ich bin immer noch sehr neu, also bin ich froh, dass ich dieses Problem gelöst habe! – VermillionAzure

Verwandte Themen