2011-11-25 32 views
10

Ho utilizzato un modello variadic che funge da firewall di eccezione in un'interfaccia tra C e C++. Il modello prende semplicemente una funzione, seguita da argomenti N e chiama la funzione all'interno di un blocco catch try. Questo ha funzionato bene, purtroppo una delle funzioni che desidero chiamare ora richiede un argomento di default aggiuntivo. Di conseguenza, il nome della funzione non viene risolto e il modello non riesce a compilare.Modelli Variadic, Inoltro perfetto alle funzioni con argomenti predefiniti

L'errore è:

perfect-forward.cpp: In function ‘void FuncCaller(Func, Args&& ...) [with Func = void (*)(const std::basic_string<char>&, double, const std::vector<int>&), Args = {const char (&)[7], double}]’ :
perfect-forward.cpp:69:41: instantiated from here
perfect-forward.cpp:46:4: error: too few arguments to function

Una versione semplificata del codice è il seguente:

template< class Func, typename ...Args > 
void FuncCaller(Func f, Args&&... params) 
{ 
    try 
    { 
     cout << __func__ << " called\n"; 
     f(params...); 
    } 
    catch(std::exception& ex) 
    { 
     cout << "Caught exception: " << ex.what() << "\n"; 
    } 
} 

void Callee(const string& arg1, double d, const vector<int>&v = vector<int>{}) 
{ 
    cout << __func__ << " called\n"; 
    cout << "\targ1: " << arg1 << "\n"; 
    cout << "\td: " << d << "\n"; 
    cout << "\tv: "; 
    copy(v.begin(), v.end(), ostream_iterator<int>(cout, " " )); 
    cout << "\n"; 
} 

int main() 
{ 
    vector<int> v { 1, 2, 3, 4, 5 }; 

    FuncCaller(Callee, "string", 3.1415, v); 
    FuncCaller(Callee, "string", 3.1415); **// Fails to compile** 

    return 0; 
} 

Qualora questo codice di lavoro o sono in attesa di troppo dal compilatore?

Nota: Ho testato l'uso di inoltro perfetto con i costruttori che hanno argomenti di default e il codice compila e funziona come previsto,

cioè:

template<typename TypeToConstruct> struct SharedPtrAllocator 
{ 
    template<typename ...Args> shared_ptr<TypeToConstruct> 
     construct_with_shared_ptr(Args&&... params) { 
     return std::shared_ptr<TypeToConstruct>(new TypeToConstruct(std::forward<Args>(params)...)); 
    }; 
}; 

opere quando si chiama il costruttore di cfollowing con 2 o 3 argomenti ...

MyClass1(const string& arg1, double d, const vector<int>&v = vector<int>{}) 
+2

(Dovrebbe essere 'f (std :: inoltro (params) ...);', a proposito.) –

risposta

8

Non credo che sia possibile raggiungere questo obiettivo. I valori degli argomenti predefiniti non fanno parte della firma della funzione. Sono solo le short-mani di generazione di codice che vengono espanse dal compilatore quando si chiama la funzione letteralmente. Allo stesso modo, std::bind non rileverà neanche gli argomenti predefiniti.

+1

Ho pensato che fosse qualcosa di lungo quelle linee ... Per interesse perché inoltra a un costruttore con argomenti predefiniti funziona? – mark

+1

Bene, puoi chiamare direttamente la funzione, che è ciò che fa il tuo codice (se risolvi tutte le sostituzioni dei parametri del template). Ma nella domanda originale, viene dedotto il tipo di funzione stesso, ed è qui che si perde l'argomento predefinito. –

Problemi correlati