2013-03-04 13 views
8

Ich möchte eine Funktion erstellen, die eine variable Anzahl von Vorlage Argumente. Später mit diesen Argumenten sollte die Funktion ihre Position wie folgt übergeben:Passing Position des variadic Vorlage Argument

template<typename R, typename Args...> 
R myFunction(Data &data, void *function) { 
    auto f = (R (*)(Args...))function; 
    return f(read<Args1>(data, 1), read<Args2>(data, 2), ...);// <-- This is the problem 
} 

Der angegebene Code ist natürlich nicht kompilierbar. Gibt es eine Möglichkeit, es zu beheben? Gibt es eine Möglichkeit, ohne variadische Vorlagen ohne zu viel Code-Duplizierung zu tun?

+2

Ich bin sicher, Sie können den Objektzeiger auf Funktionszeiger-Cast vermeiden. – sellibitze

+0

@sellibitze: Ist das ein Problem? Weil ich nur void * pointer Benutzerdaten haben kann, die von einer C-Funktion übergeben werden. –

+0

Die Daten können ein 'void *' sein. Es ist die Funktion, eine "Leere" zu sein, die ein Problem darstellt. –

Antwort

14

Ja, das ist möglich:

// we need a compile-time helper to generate indices 
template< std::size_t... Ns > 
struct indices 
{ 
    typedef indices< Ns..., sizeof...(Ns) > next; 
}; 

template< std::size_t N > 
struct make_indices 
{ 
    typedef typename make_indices< N - 1 >::type::next type; 
}; 

template<> 
struct make_indices<0> 
{ 
    typedef indices<> type; 
}; 

Mit diesen Helfern, benötigen Sie einen Spediteur für Ihre Funktion wie folgt aus:

template<typename R, typename... Args, std::size_t... Ns> 
R myFunctionImpl(void *Data, void *function, indices<Ns...>) { 
    auto f = (R (*)(Args...))function; 
    return f(read<Args>(Data, Ns + 1)...);// +1 because indices is zero-based 
} 

template<typename R, typename... Args> 
R myFunction(void *Data, void *function) { 
    return myFunctionImpl< R, Args... >(Data, function, typename make_indices<sizeof...(Args)>::type()); 
} 

EDIT: Wie funktioniert es? Zuerst bestimmen wir die Größe des argument packArgs durch . make_indices<N>::type expandiert dann in indices<0,1,2,...,N-1>. Es wird als zusätzlicher Parameter für die Implementierungsfunktion angegeben (von der Weiterleitung, die nur eine Dummy-Instanz erstellt), daher beginnt der Argumentabzug auf der Seite der Implementierungsfunktion und setzt die generierten Indizes in das Argumentpack Ns.

Die Implementierungsfunktion hat jetzt zwei Argumentpakete mit der gleichen Größe, nämlich Args und Ns. Wenn sie durch die Ellipse ... erweitert wird, erweitert die Ellipse den ganzen Ausdruck, auf den es angewendet wird, und es erweitert alle Parameterpakete parallel! Im obigen Beispiel ist dieser Ausdruck read<Args>(Data, Ns+1), was sich schön in den OPs-Pseudocode erweitert.

+0

können Sie ein einfaches Beispiel veröffentlichen? –

+2

habe ich gerade getan. Was fehlt in dem Beispiel, das ich gab? –

+0

Was fehlt, ist ein echtes Beispiel. Mit 'main()' und einigen Funktionen (mit 1,2,3 Parametern). Wie nutzen Sie diese Funktionen und Strukturen? –

Verwandte Themen