2013-02-27 13 views
5

Sto scrivendo una libreria che comporta una buona quantità di enigmi del template e boost :: any. Ho eseguito in una situazione in cui ho essenzialmente ho questo:boost :: any e templates

boost::any a1, a2, a3, a4; 

... e ho bisogno di chiamare una funzione che assomiglia a questo:

template <typename A1, typename A2, typename A3, typename A4> 
void somefunc (A1 a1, A2 a2, A3 a3, A4 a4); 

potrei ricorrere ad una serie nidificato oscenamente di istruzioni if, ma supponendo che sto gestendo 10 tipi distinti, sono 10.000 se le affermazioni! Potenziare il preprocessore potrebbe aiutare qui, ma questa è ancora una soluzione orribile.

C'è un modo migliore per chiamare una funzione basata su modelli con il contenuto di una spinta: nessuna senza ricorrere a questo tipo di follia? Per quanto posso dire, non c'è.

+0

Solo l'utente del 'boost :: any' istanza può ottenere il valore esatto in fase di esecuzione (fornendo un tipo con hardcoded), non è possibile chiamare tale funzione con il valore contenuto in 'boost :: any' perché il tipo è stato * cancellato * in fase di compilazione. Qual è il problema più grande che stai cercando di risolvere? 'boost :: any' è roba piuttosto di basso livello. – GManNickG

+3

Tutti gli oggetti 'any' come un oggetto, e quando li si impostano tutti insieme, anche un puntatore sicuro alla corretta istanza' somefunc' (ad esempio '& somefunc '). – Xeo

+0

@GManNickG il problema più grande che sto cercando di risolvere riguarda l'auto-generazione dei binding Lua su un lato, e un boost :: any che tiene il risultato di una funzione asincrona arbitraria. Nessuno dei due può essere sostituito con l'altro in questa situazione. – Xtapolapocetl

risposta

10

Se tutti gli oggetti any possono essere impostati contemporaneamente, è possibile semplicemente codificare il tipo per il puntatore funzione in quel momento. Metti tutto in un oggetto separato e sei a posto. Questo è fondamentalmente un Double-Take on type-erasure, e potrebbe essere realizzata anche attraverso le funzioni virtuali (come il modo boost::any funziona internamente), ma mi piace questa versione più:

// note that this can easily be adapted to boost::tuple and variadic templates 
struct any_container{ 
    template<class T1, class T3, class T3> 
    any_container(T1 const& a1, T2 const& a2, T3 const& a3) 
    : _ichi(a1), _ni(a2), _san(a3), _somefunc(&somefunc<T1, T2, T3>) {} 

    void call(){ _somefunc(_ichi, _ni, _san); } 

private: 
    boost::any _ichi, _ni, _san; 
    // adjust to your need 
    typedef void (*func_type)(boost::any&, boost::any&, boost::any&); 
    func_type _somefunc; 

    template<class T1, class T2, class T3> 
    void somefunc(boost::any& a1, boost::any& a2, boost::any& a3){ 
    // access any objects with 'boost::any_cast<TN>(aN)' 
    } 
}; 
+0

Brillante, grazie. – Xtapolapocetl

+0

+1, in particolare per le variabili _ichi, _ni e _san. –