最近,我遇到了一个奇怪的问题,将一个函数作为参数传递给lambda表达式。使用clang 3.5+编译得很好,但g ++ 5.3失败,我不知道问题出在C++标准中,clang中是非标准的扩展,还是GCC中的无效语法解释。C++ 11传递函数作为lambda参数
的示例代码是仙女简单:
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报告了以下:
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)
幸运的是,我发现了一个简单的解决方法,增加一个std ::函数对象,封装所述功能参数:
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();
};
尽管我并不完全理解冷杉中的错误,一段代码,用clang成功编译并运行没有错误。
编辑
我刚刚注意到,我的解决方案灾难性故障时,如果其中一个参数应该是一个参考。因此,如果您有任何其他建议可能与C++ 11一起工作(即没有专门的lambda捕获[C++ 14功能]),那将非常酷...
如果传递'自动p_fn会发生什么= &fn'到lambda? –
@JoelCornett sigsegv或类似的东西。同样的事情发生在传递'fn'作为参考。虽然它编译,在这两种情况下。 – Marandil