Recentemente, ho riscontrato un problema strano con il passaggio di una funzione passata come parametro a un'espressione lambda. Il codice è stato compilato correttamente con clang 3.5+, ma non è riuscito con g ++ 5.3 e mi chiedo se il problema sia nello standard C++, un'estensione non standard in clang o un'interpretazione sintattica non valida in GCC.C++ 11 Funzione di passaggio come parametro lambda
Il codice di esempio è fata semplice:
template<typename Fn, typename... Args, typename T = typename std::result_of<Fn(Args...)>::type>
std::future<T>
async(Fn &&fn, Args &&... args)
{
std::shared_ptr<std::promise<T>> promise = std::make_shared<std::promise<T>>();
auto lambda = [promise, fn, args...](void)
{ promise->set_value(fn(std::move(args)...)); };
send_message(std::make_shared<post_call>(lambda));
return promise->get_future();
};
GCC ha riportato il seguente:
error: variable ‘fn’ has function type
{ promise->set_value(fn(std::move(args)...)); };
(...)
error: field ‘async(Fn&&, Args&& ...) [with Fn = int (&)(int, int); Args = {int&, int&}; T = int]::<lambda()>::<fn capture>’ invalidly declared function type
auto lambda = [promise, fn, args...](void)
Per fortuna, ho trovato una soluzione semplice, l'aggiunta di un oggetto std :: funzione, incapsulando il parametro della funzione :
template<typename Fn, typename... Args, typename T = typename std::result_of<Fn(Args...)>::type>
std::future<T>
async(Fn &&fn, Args &&... args)
{
std::shared_ptr<std::promise<T>> promise = std::make_shared<std::promise<T>>();
std::function<T(typename std::remove_reference<Args>::type...)> floc = fn;
auto lambda = [promise, floc, args...](void)
{ promise->set_value(floc(std::move(args)...)); };
send_message(std::make_shared<post_call>(lambda));
return promise->get_future();
};
Anche se non capisco cosa c'era di sbagliato negli abeti t pezzo di codice, compilato con successo con clang e eseguito senza errori.
EDIT
Ho appena notato, che la mia soluzione non riesce in modo catastrofico, se uno degli argomenti doveva essere un punto di riferimento. Quindi, se avete altri suggerimenti che potrebbero funzionare con C++ 11 (cioè senza lambda specializzata [C++ 14 feature]), sarebbe davvero bello ...
Che cosa succede se si passa 'p_fn auto = & fn' a lambda? –
@JoelCornett sigsegv o qualcosa di simile. La stessa cosa è accaduta con il passaggio di 'fn' come riferimento. Sebbene compili, in entrambi i casi. – Marandil