2015-02-19 12 views
5

Di seguito è disponibile una funzione di modello denominata ProxyCall, che accetta un oggetto, una funzione membro e i relativi argomenti. Semplicemente inoltra la chiamata alla funzione membro.Deduzione di tipo di riferimenti const in funzioni di modello

Vorrei essere in grado di chiamare la funzione senza utilizzare i qualificatori di modello (si immagini tonnellate di tali chiamate con più argomenti). La deduzione di tipo funziona principalmente ma i compilatori (entrambi msvc e gcc 4.9) barf quando provo a passare i parametri di riferimento const come nell'esempio.

#include <string> 

struct Widget { 
    void f(const std::string& s, bool b) {} 
}; 


template<typename T, typename... Args> 
void ProxyCall(T &obj, void(T::*method)(Args...), Args&&... args) { 
    (obj.*method)(std::forward<Args>(args)...); 
} 


int main(int argc, char* argv[]) 
{ 
    Widget w; 
    std::string s; 

    ProxyCall<Widget, const std::string&, bool>(w, &Widget::f, s, true); // OK 
    ProxyCall(w, &Widget::f, (const std::string&)s, true); // also OK 

    ProxyCall(w, &Widget::f, s, true); // ERROR: template parameter is ambiguous 
    return 0; 
} 

La mia domanda è: come posso modificare il codice di cui sopra in modo che il compilatore dedurre automaticamente i tipi senza ricorrere alla qualificazione dei modelli espliciti o cast esplicito. Sembra che questo dovrebbe essere possibile considerando che il compilatore conosce già i tipi di argomenti esatti dalla firma di Widget :: f.

+1

'template void ProxyCall (T & obj, metodo M, Args && ... args) ' – zch

+1

o in alternativa' template void ProxyCall (T & obj, void (T: : * metodo) (Margs ...), Args && ... args) ' – zch

risposta

3
template<typename T, typename... Args> 
void ProxyCall(T &obj, void(T::*method)(Args...), Args&&... args) { 
    (obj.*method)(std::forward<Args>(args)...); 
} 

Args si deduce sia dal secondo argomento e gli argomenti di trascinamento a ProxyCall.
Nel terzo caso, poiché s non è const, Args viene dedotto a [std::string&, bool] (richiamare le regole per riferimenti di compressione e inoltro riferimenti). Tuttavia, la firma delle funzioni membro è chiaramente diversa. Quindi due tipi diversi sono dedotti per il primo tipo in Args, che porta a un errore di deduzione.

Invece, fare entrambi i tipi di parametri e gli argomenti indipendenti - e in avanti l'argomento oggetto, per il bene di ref-qualificazioni:

template<typename T, typename F, typename... Args> 
void ProxyCall(T&& obj, F method, Args&&... args) { 
    (std::forward<T>(obj).*method)(std::forward<Args>(args)...); 
} 
Problemi correlati