2010-07-23 17 views
17

Si prega di guardare il seguente C++ 0x lambda relativo codice:C++ 0x lambda, come posso passare come parametro?

typedef uint64_t (*WEIGHT_FUNC)(void* param); 
typedef std::map<std::string, WEIGHT_FUNC> CallbackTable; 

CallbackTable table; 
table["rand_weight"] = [](void* param) -> uint64_t 
{ 
    return (rand() % 100 + 1); 
}; 

ho ottenuto un errore (in Visual Studio 2010) che la lambda non poteva essere convertito nel tipo di WEIGHT_FUNC. So anche la risposta: utilizzando std::function object:

typedef std::function<uint64_t (void*)> WEIGHT_FUNC; 

Tuttavia, vorrei anche sapere come posso ricevere il tipo di lambda SENZA usando std::function. Che tipo dovrebbe essere?

+1

'auto'? _______ – kennytm

+2

auto sarà utile per determinare automaticamente il tipo, non è un tipo di variante, non può essere un parametro. – Klaim

+2

Quale compilatore stai usando? Sembra che il tuo compilatore non sia standard per quanto riguarda i lambda, dovrebbero essere in grado di convertire implicitamente in un puntatore a funzione (in casi come questo.) – GManNickG

risposta

20

La conversione di funzionare puntatore è relativamente nuovo: E 'stato introdotto con N3043 il 15 febbraio 2010.

Mentre per esempio GCC 4.5 lo implementa, Visual Studio 10 è stato rilasciato il 12 aprile 2010 e quindi non è stato implementato in tempo. Come James ha sottolineato, questo will be fixed nelle versioni future.

Per il momento è necessario utilizzare una delle soluzioni alternative fornite qui.

Tecnicamente qualcosa come la seguente soluzione avrebbe funzionato, ma senza variadic Modelli la sua non è divertente per generalizzare (Boost.PP in soccorso ...) e non v'è alcuna rete di sicurezza contro il passaggio cattura lambda in:

typedef uint64_t (*WeightFunc)(void* param); 

template<class Func> WeightFunc make_function_pointer(Func& f) { 
    return lambda_wrapper<Func>::get_function_pointer(f); 
} 

template<class F> class lambda_wrapper { 
    static F* func_; 
    static uint64_t func(void* p) { return (*func_)(p); }  
    friend WeightFunc make_function_pointer<>(F& f);  
    static WeightFunc get_function_pointer(F& f) { 
     if (!func_) func_ = new F(f); 
     return func; 
    } 
}; 

template<class F> F* lambda_wrapper<F>::func_ = 0; 

// ... 
WeightFunc fp = make_function_pointer([](void* param) -> uint64_t { return 0; }); 
+8

Vale la pena ricordare che la conversione ai puntatori funzione è solo per funzioni lambda stateless, non possono acquisire scope lessicali. –

+0

La conversione al puntatore di funzione sembra non funzionare con g ++ 4.5 nel codice template (http://tinyurl.com/3y6hkyq) – rafak

+0

Vedere http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45080 per quello . –

-1

Prova con (non testato):

#include <function> 

typedef std::function< int64_t (void*) > weight_func; 
typedef std::map<std::string, weight_func > CallbackTable; 

Non credo ci sia altro modo per farlo che per usare std :: funzione o equivalente.

+0

Grazie per la correzione sbi – Klaim

+3

Non utilizzare 'std :: function ', utilizzare 'std :: function '. –

+0

Giusto! Risolto, grazie! – Klaim

1

Se proprio insistete a non utilizzare function<> allora probabilmente si potrebbe utilizzare decltype:

typedef decltype([](void*)->uint_64{return 0;}) my_lambda_type; 

davvero non consiglio questo però dato che si sta drasticamente te limitante e non si sa nemmeno se due le lambda con la stessa firma sono garantite dallo stesso tipo.

+0

È garantito che il tipo generato sarà lo stesso di se si scrive esattamente lo stesso typedef da qualche parte altro? Non penso che dovresti assumere che il tipo dipende dalla firma ... ma forse ho torto. – Klaim

+0

Non funziona in GCC. –

+1

Vecchia risposta, lo so, ma l'espressione lambda non può apparire in un contesto non valutato. (Penso che la logica sia ciò che hai sollevato: poiché ogni espressione lambda è un tipo unico e non specificato, non ti è garantita alcuna particolare risposta significativa e un contesto non valutato.) – GManNickG

Problemi correlati