2015-08-14 20 views
12

ideone exampleargomenti di inoltro per la funzione di membro template


ho bisogno di trasmettere alcuni argomenti predefiniti oltre ad alcuni argomenti dall'utente passato a una funzione membro.

#define FWD(xs) ::std::forward<decltype(xs)>(xs) 

template<class T, class... Ts, class... TArgs> 
void forwarder(void(T::*fptr)(Ts...), TArgs&&... xs) 
{ 
    T instance; 
    (instance.*fptr)(FWD(xs)..., 0); 
    //       ^
    // example predefined argument 
} 

forwarder(&example::f0, 10, 'a'); 
forwarder(&example::f1, 10, "hello", 5); 

Questo funziona correttamente per le funzioni membro non di modello.

Il puntatore della funzione membro passato a forwarder può, tuttavia, puntare anche alle funzioni del modello. Purtroppo, il compilatore non è in grado di dedurre il tipo di T in quel caso:

struct example 
{ 
    void f0(int, int) { } 

    template<class T> 
    void f1(T&&, int) { } 
}; 

// Compiles 
forwarder(&example::f0, 10); 

// Does not compile 
forwarder(&example::f1, 10); 

Errori:

prog.cpp:30:28: error: no matching function for call to 'forwarder(<unresolved overloaded function type>, int)' 
    forwarder(&example::f1, 10); 
          ^
prog.cpp:20:6: note: candidate: template<class T, class ... Ts, class ... TArgs> void forwarder(void (T::*)(Ts ...), TArgs&& ...) 
void forwarder(void(T::*fptr)(Ts...), TArgs&&... xs) 
    ^
prog.cpp:20:6: note: template argument deduction/substitution failed: 
prog.cpp:30:28: note: couldn't deduce template parameter 'T' 
    forwarder(&example::f1, 10); 

C'è un modo per aiutare il compilatore dedurre il tipo corretto senza cambiare l'interfaccia di forwarder?

In caso contrario, qual è il modo migliore per risolvere questo problema senza rendere troppo complicata la sintassi dell'utente?

MODIFICA: Sarebbe anche accettabile passare il puntatore a funzione membro come parametro di modello, magari attraverso un wrapper. La funzione membro di destinazione sarà sempre nota in fase di compilazione. Pseudocodice:

forwarder<WRAP<example::f0>>(10, 'a'); 
// Where WRAP can be a macro or a type alias. 

ideone example

+0

È ancora possibile eseguire un cast per risolvere il problema di ambiguità ([cf questo fork del tuo esempio] (http://ideone.com/942rPt)) ma non sono sicuro che ti soddisfi ... – Caninonos

+0

Don ' so se questo ti si addice, ma http://coliru.stacked-crooked.com/a/3507a8671c1162c2 – 0x499602D2

+0

@Caninonos: sembra troppo fastidioso scrivere per l'utente. Se non c'è altra soluzione migliore, potrei scrivere una funzione di aiuto 'forwarder' e una semplice macro che si espande in' decltype' per tutti gli argomenti passati ... ma la terrò come ultima risorsa. –

risposta

1

ho compilato il codice in gcc 4.9, fornendo argomenti di template per il puntatore a funzione membro; come questo

int main(){ 
// Compiles 
forwarder(&example::f0, 10); 
//Does not compile 
forwarder(&example::f1, 10); 
//Does compile, instantiate template with int or what ever you need 
forwarder(&example::f1<int>,10) 
} 

Credo che quello che sta succedendo è che è necessario creare un'istanza della funzione di membro template. cambia la tua interfaccia troppo? Penso che ogni risposta ruoterà attorno all'istanziazione di quel modello membro in qualche modo.

Problemi correlati