【问题标题】:Using auto in a lambda function在 lambda 函数中使用 auto
【发布时间】:2011-12-04 07:47:47
【问题描述】:
#include <vector>
#include <algorithm>

void foo( int )
{
}

int main()
{
  std::vector< int > v( { 1,2,3 } );

  std::for_each( v.begin(), v.end(), []( auto it ) { foo( it+5 ); } );
}

编译后,上面的例子开始错误输出是这样的:

h4.cpp: In function 'int main()':
h4.cpp:13:47: error: parameter declared 'auto'
h4.cpp: In lambda function:
h4.cpp:13:59: error: 'it' was not declared in this scope

这是否意味着关键字auto不应该在lambda表达式中使用?

这行得通:

std::for_each( v.begin(), v.end(), []( int it ) { foo( it+5 ); } );

为什么带有auto关键字的版本不起作用?

【问题讨论】:

  • 我认为即使是lambda,它仍然可以作为函数工作,并且必须有签名。使用 auto 你让编译器决定类型,所以你的 lambda 在编译时没有真正的签名。
  • 我们在下一个标准中确实需要多态 lambdas(AKA 隐式模板)。这个问题只是人们假设auto 以这种方式工作的几个例子之一。我认为没有理由不应该这样做。
  • deft_code ,我和你在一起。这是自动的逻辑用例。

标签: c++ c++11 auto lambda


【解决方案1】:

auto 关键字在 C++11 中不能用作函数参数的类型。如果你不想在 lambda 函数中使用实际类型,那么你可以使用下面的代码。

 for_each(begin(v), end(v), [](decltype(*begin(v)) it ){
       foo( it + 5);         
 });

问题中的代码在 C++ 14 中运行良好。

【讨论】:

  • 我们将在 C++14 的 lambdas 中获得 auto 支持。
  • 注意decltypebegin(v) 之前的星号。您想要值类型而不是迭代器类型。 (失败时的错误消息会很神秘)。
【解决方案2】:

C++14 允许使用自动声明 lambda 函数(通用 lambda 函数)参数。

auto multiply = [](auto a, auto b) {return a*b;};

详情:http://en.cppreference.com/w/cpp/language/lambda

【讨论】:

    【解决方案3】:

    Herb Sutter 在一次采访中简要讨论了这一点。您对 auto 参数的要求实际上与要求 any 函数应该可以用 auto 声明没有什么不同,如下所示:

    auto add(auto a, auto b) -> decltype(a + b) { return a + b; }
    

    但是,请注意,这根本不是一个函数,而是一个 模板 函数,类似于:

    template <typename S, typename T>
    auto add(S a, T b) -> decltype(a + b) { return a + b; }
    

    因此,您实际上是在要求一种工具,通过更改其参数将任何函数转换为模板。由于模板是 C++ 类型系统中一种非常不同的实体(想想模板的所有特殊规则,如两阶段查找和推导),这将是具有不可预见的后果的根本设计变化,这当然不是很快就会成为标准。

    【讨论】:

    • 不,没有要求或要求 :) 我只是想知道为什么它不起作用。
    • 嗯,这与“为什么不是所有的函数模板”的原因基本相同——它只是不适合语言的设计。
    【解决方案4】:

    在编译器甚至可以实例化std::for_each 之前,需要知道 lambda 的类型。另一方面,即使理论上可行,auto 也只能在 for_each 被实例化后通过查看仿函数的调用方式来推断。

    如果可能的话,忘记for_each,并使用更简单的基于范围的for循环:

    for (int it : v) { 
       foo(it + 5); 
    }
    

    这也应该很好地处理auto(以及auto&amp;const auto&amp;)。

    for (auto it : v) { 
       foo(it + 5); 
    }
    

    【讨论】:

    • 是的,但这仅适用于 for_each,不适用于其他算法。例如您想对 lambda 进行排序。
    猜你喜欢
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    • 2022-01-19
    • 2013-10-22
    • 1970-01-01
    • 1970-01-01
    • 2019-07-10
    • 1970-01-01
    相关资源
    最近更新 更多