【问题标题】:How to be explicit about the type of a captured variable in a lambda?如何明确 lambda 中捕获的变量的类型?
【发布时间】:2019-10-12 08:55:56
【问题描述】:

如何在 C++ 中为 lambda 显式指定捕获变量的类型?

例如,假设我有一个接受通用引用的函数,并且我想将其完美转发到 lambda。

我发现,我可以使用std::tuple,如下所示,但我想知道是否有更简洁的方法。

template<typename T>
auto returns_functor (T&& value)
{
  return [value = std::tuple<T> (std::forward<T> (value))] ()
  {
    /* use std::get<0> (value) */
  };
}

相关:Capturing perfectly-forwarded variable in lambda(那里接受的答案表明这是一个不同的问题,但进一步的答案基本上给出了上述解决方案)。

【问题讨论】:

  • 如果你把它保留为T 有什么优点来指定它?
  • value = std::forward&lt;T&gt;(value) 有什么问题?
  • @HolyBlackCat 那不是总是按副本捕获吗?
  • @RaymondChen 在该示例中,您传入了一个右值引用,因此它将被移动到 tuple&lt;string&gt; 中,并且没有生命周期问题。可能的问题是如果你传入一个左值引用,然后让 lambda 活得更久。
  • @HolyBlackCat 它会复制或移动,但它永远不会持有引用。所以不能算完美转发。此外,如果您只需要复制或移动,那么您只需指定[value]

标签: c++ lambda capture


【解决方案1】:

另一种获取右值(通用引用)的方式如下,

template< typename T>
T getRvalue( T&& temp)
{
  auto lambda = [ rTemp = std::move( temp)]() mutable
  {
     return T( std::forward< T>( rTemp));
  };

  return lambda();
}

std::move() 允许捕获无法通过复制捕获的可移动类型的对象。 mutable在lambda这里非常重要,直到没有使用mutable,lambda捕获的对象都不能修改,编译会产生如下错误,

cannot conver 'rTemp (type 'const T') to type 'std::remove_reference<T>::type&' {aka 'T&'}
return T( std::forward< T>( rTemp));

现在关于第一个问题,
“如何在 C++ 中为 lambda 显式指定捕获变量的类型?”

所以不需要指定类型,编译会做,见以下链接,

https://en.cppreference.com/w/cpp/language/lambda

上面写着A capture with an initializer acts as if it declares and explicitly captures a variable declared with type auto, whose declarative region is the body of the lambda expression. 简单来说就是自动变量是根据初始化器推导出来的,不需要明确指定它的类型,例如

int x = 1;
auto lambda = [ y = x + 2](){ std::cout<< "y = "<< y<< std::endl;};

这里的y 将被初始化器x + 2 推导出为int

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多