2014-11-18 22 views
6

Ho la seguente C++ 11 esempio in cui ho una funzione call che utilizza modelli variadic ad accettare e chiamare un metodo di una classe generica:incoerente detrazione parametro pacco con i modelli variadic

#include <utility> 

template <typename T, typename R, typename... Args> 
R call(R (T::*fn)(Args...), T *t, Args&&... args) { 
    return ((*t).*fn)(std::forward<Args>(args)...);  
} 

class Calculator { 
    public: 
    int add(const int& a, const int& b) { 
     return a + b; 
    } 
}; 

int main() { 
    Calculator *calculator = new Calculator(); 
    int* a = new int(2);  
    int* b = new int(4); 

    // compiles 
    int res1 = calculator->add(*a, *b);  

    // does not compile! 
    int res2 = call<Calculator>(&Calculator::add,calculator, *a, *b);  

    return 0; 
} 

Come commentato nel codice , Non sono in grado di passare un quando la funzione accetta const int, mentre nella chiamata di metodo direzione posso. Ottengo il seguente errore di compilazione:

error: no matching function for call to ‘call(int (Calculator::*)(const int&, const int&), Calculator*&, int&, int&)’ 
    int res2 = call<Calculator>(&Calculator::add,calculator, *a, *b);  
                    ^

inconsistent parameter pack deduction with ‘const int&’ and ‘int&’ 
    int res2 = call<Calculator>(&Calculator::add,calculator, *a, *b);  
                    ^

Ha C++ template variadic far rispettare severe controllo di tipo rispetto alla regolare esecuzione? Sto usando g ++ 4.8.1 con C++ 11.

+0

Forse ti piace l'errore di Clang meglio: * Nota: template candidato ignorato: dedotto tipi contrastanti per il parametro 'Args' ( vs. ) * – chris

+0

Ciò significa che i tipi devono corrispondere esattamente quando si utilizzano i modelli variadic? – jeffreyveon

+1

Significa che non è possibile dedurre tipi diversi per lo stesso parametro del modello perché il compilatore non può sapere quale si desidera. È sempre possibile saltare l'acquisizione della funzione esplicita e avere semplicemente un parametro oggetto richiamabile: 'template auto call (F f, T * t, Args && ... args) { return (t -> * f) (std :: forward (args) ...); } ' – chris

risposta

11

Il modo in cui si sta chiamando il vostro modello di funzione, il parametro Template Pack Args sarà dedotta da due fonti:

  • Il tipo di puntatore a membro funzione - int (Calculator::*)(const int&, const int&)
  • i tipi effettivi degli argomenti (*a, *b) è stato passato per il parametro funzione pack - int &, int &

per deduzione per avere successo, il risultato dedotto deve exac abbinare Ovviamente no.

Questo non è nuovo o speciale per i modelli variadic. Hai lo stesso problema se provi a fare std::max(1, 1.5) - il compilatore deduce da un argomento, double dall'altro, e la deduzione non riesce perché i due conflitti.

più semplice correzione è probabilmente prendendo due pacchetti:

template <typename T, typename R, typename... Args1, typename... Args2> 
R call(R (T::*fn)(Args1...), T *t, Args2&&... args) { 
    return ((*t).*fn)(std::forward<Args2>(args)...);  
} 
+0

Ovviamente :) Grazie. – jeffreyveon

Problemi correlati