我怎样才能返回一个lambda对象?

时间:2014-04-03 02:20:52

标签: c++ c++11 lambda c++14

我想从函数返回一个lambda对象,而不将其转换为函数指针或函数对象。更具体地说,我想让它留给客户端决定是否转换为函数对象或将lambda保留为匿名函数:

template<typename F> // F may be a std::function, boost::function, or lambda object
auto func(F f) -> decltype(???) // what do I put in here?
{
    return [=]()
    {
        return f(someParameter);
    }
}

此代码无效,因为我不知道要推断的类型。一种选择可能是将lambda的主体复制到decltype调用中。当然有更好的方法!

我想要这样做的理由是,我希望让编译器能够更智能地内联或展开lambda。这种推理有意义吗?如果是这样,为什么,何时更简单地返回std::function?这种方法在编译时可能会变慢吗?

3 个答案:

答案 0 :(得分:9)

在C ++ 11中,你无法做到这一点。你可以做一些接近它的事情,但不是这个。

基本上,提取一种C ++ 11 lambda的唯一方法是从类型的实例中推导出它,并且不能在未评估的上下文中命名该类型。因此函数不能返回类型取决于lambda类型的类型。 (除非在函数声明之前声明lambda,使用body,在这种情况下没有用)。您可以编写一个作为手动函数对象的仿函数,或使用std::bind为您执行此操作。

你可以让它评估一些你也传入lambda的其他函子,但是这会变得很尴尬(特别是在C ++ 11中,这些函子要么必须键入erase,要么必须是写入的旧式函子& #34;手动&#34;作为structclass)。

C ++ 1y中添加的功能之一使其变得简单:

template<typename F, typename T>
auto func(F f, T t) {
  return [=]() {
    return f(t);
  };
}
int main() {
  auto f = func( [](int x){ std::cout << x << "\n"; }, 7 );
  f();
  f();
}

Live example

您的编译器可能已经为此功能提供了C ++ 1y支持。

答案 1 :(得分:1)

  • 在C ++ 11中,使用std::function<...>

  • 键入擦除
  • 在C ++ 14中,不需要decltype,所以你可以这样做:

    auto f() { return //lambda here }

你现在可以做的一切。

Clang声称在其版本3.4中有完整的c ++ 14支持,正如目前的草案一样。 Gcc在即将推出的gcc 4.9中支持全面支持,并在gcc 4.8中支持部分支持。

答案 2 :(得分:0)

AFAIK,如果您使用lambda捕获内容,则通常不能在std::function

之类的容器外表示

然后,我认为编译器无法内联返回的lambda,因为它在函数调用之前不存在。

所以你生成它,并在执行时加载它的状态并做它的事情。

  

如果是这样,为什么,何时更简单地返回std :: function?

<强>为什么吗

这是标准库。可能与客户一样多的自由。您可以从中提取lambda,或函数指针或函数等。 (请查看target http://en.cppreference.com/w/cpp/utility/functional/function/target

:当吗

如果要返回封装的函数。

它是否回答或者我是否错过了你的观点? Lambdas非常酷,但我担心我(和许多人)在学习曲线的开头高估了它们(特别是在性能方面,将它们视为自生代码巫术)