2013-06-14 11 views
9

Ich möchte eine Funktion mit den Argumenten aufrufen, die von einem Vektor kommen. Dies allein ist sicherlich sehr einfach, aber ich würde gerne einen generischen Wrapper schreiben, der die Aufgabe für mich übernimmt. Später sollte es auch die Konvertierung von einem generischen Typ wie boost :: variant machen, aber ich denke, dass ich damit umgehen kann, nachdem dieses Problem gelöst ist.Generische Vorlage zum Aufrufen von Funktionen mit Vektorelementen

Dies ist mein erster Versuch:

#include <iostream> 
#include <functional> 
#include <vector> 

using namespace std; 

void foo(int a, int b) 
{ 
    cout << a*10+b << endl; 
} 

template<class... Args> 
void callByVector(std::function<void(Args...)> f, vector<int>& arguments) 
{ 
    int i = 0; 
    f(static_cast<Args>(arguments[i++])...); 
} 

int main() 
{ 
    vector<int> arguments; 
    arguments.push_back(2); 
    arguments.push_back(3); 

    callByVector(std::function<void(int,int)>(foo),arguments); 
} 

Es funktioniert, aber wie Sie sich vorstellen können, die Reihenfolge der Ausführung der Inkremente ist nicht definiert. Daher kann das Gesamtergebnis 23 oder 32 sein (das kann ich mit verschiedenen Compilern bestätigen).

Irgendwelche Ideen oder muss ich das vergessen?

Grüße, Florian

+1

Kann Vektor mit Tupel ersetzt werden? Wenn ja, dann denken Sie darüber nach, wie Sie das Tupel in die Argumente von f entpacken können. – Tomek

+0

@Tomek: Für meine Anwendung finde ich das nicht möglich, aber es klingt trotzdem interessant. Wie kann ich das machen? Nur mein Tupel ...? – koalo

Antwort

11

Sie können Indizes für diesen Zweck verwendet werden. Vor diesem Generator von Kompilierung-Integer-Sequenzen:

template<int... Is> 
struct seq { }; 

template<int N, int... Is> 
struct gen_seq : gen_seq<N - 1, N - 1, Is...> { }; 

template<int... Is> 
struct gen_seq<0, Is...> : seq<Is...> { }; 

Sie können Ihre ursprüngliche Funktion delegieren die Arbeit zu einer Hilfsfunktion aufgerufen, mit einem zusätzlichen Argument lassen, die die Folge von ganzen Zahlen ermöglicht herzuleiten. Argument Pack Erweiterung würde den Rest:

template<class... Args, int... Is> 
void callByVector(
    std::function<void(Args...)> f, vector<int>& arguments, seq<Is...>) 
{ 
    f(arguments[Is]...); 
} 

template<class... Args> 
void callByVector(std::function<void(Args...)> f, vector<int>& arguments) 
{ 
    callByVector(f, arguments, gen_seq<sizeof...(Args)>()); 
} 

hier ein live example ist.

+0

Das sieht gut aus! Ich danke dir sehr! Ich hätte früher fragen sollen ... – koalo

+0

@koalo: Froh, dass es geholfen hat :) –

Verwandte Themen