【问题标题】:C++: use of Lambda function inside the accumulate method from <numeric>C++:在 <numeric> 的累积方法中使用 Lambda 函数
【发布时间】:2021-10-14 11:54:39
【问题描述】:

我有一个二维的vector&lt; vector&lt;int&gt; &gt;,比如说

contests = [[5, 1], [2, 1], [1, 1], [8, 1], [10, 0], [5, 0]]

我想使用accumulate 来获取第一个元素的总和,因此我使用 lambda 函数来访问向量向量中的正确维度:

#include <iostream>
#include <vector>
#include <numeric>

int main() {
    std::vector< std::vector<int> > 
        contests = {{5, 1}, {2, 1}, {1, 1}, {8, 1}, {10, 0}, {5, 0}};
    int sum = std::accumulate(contests.begin(),contests.end(), 0, 
                  [](const std::vector<int>& a, const std::vector<int>& b)->int 
                      {return a[0] + b[0];}
              );
    
    std::cout << sum << std::endl;
    
    return 0;
} 

我得到一个很长的编译错误,最后一行指出:

    note: candidate: ‘main(int, std::vector<std::vector<int> >)::<lambda(const std::vector<int>&, const std::vector<int>&)>’
                     [](const vector<int>& a, const vector<int>& b)->int {return a[0] + b[0];}
                                                       ^~~
main.cpp:37:55: note:   no known conversion for argument 1 from ‘int’ to ‘std::vector<int>’

如何让 lambda 识别正确的参数?

【问题讨论】:

  • 更喜欢通过 const 引用而不是通过值传递 std::vector 以避免复制。
  • 难道 lambda 不会创建自己的任何捕获参数的副本吗?
  • 你的 lambda 没有捕获任何东西。无论如何,对于捕获,您也可以选择按值或按引用捕获。
  • 你是对的,只有捕获的变量被克隆,而 lambda 已经访问的变量(如我的例子)可以被引用:“Lambdas can only access specific types of identifiers: global identifiers, entitys在编译时已知的,以及具有静态存储持续时间的实体。捕获子句用于为 lambda 提供对其通常无法访问的周围范围内可用变量的访问权限。当执行 lambda 定义时,对于每个变量lambda 捕获后,会在 lambda 内部生成该变量的克隆(具有相同的名称)。”

标签: c++ c++11 lambda


【解决方案1】:

问题在于传递的函子中的参数类型。让我们看看文档:

...将要应用的二元运算函数对象。二进制 运算符取当前累积值 a(初始化为init) 以及当前元素的值 b - cppreference.com

这正是错误消息所说的内容:no known conversion from ‘int’ to ‘std::vector&lt;int&gt;‘,因为std::accumulate 将当前累积值 int 传递给在其第一个参数中需要 std::vector&lt;int&gt; 的函子。

因此,您的函子必须具有以下形式:

// Pass currently accumulated value and the value of the current element
[](int current, const std::vector<int>& b)->int {return current + b[0];}

例子:

std::vector<std::vector<int>>
    contests = {{5, 1}, {2, 1}, {1, 1}, {8, 1}, {10, 0}, {5, 0}};

int sum = std::accumulate(contests.begin(), contests.end(), 0, 
          [](int current, const std::vector<int>& b)->int {return current + b[0];});

std::cout << sum << std::endl;

打印:

31

【讨论】:

  • 没看到,什么盲点
【解决方案2】:

通过使用auto,类型推导留给编译器。然后你可能已经注意到了很多具体的错误。所以最好使用auto

使用自动,下面的代码可能会产生很多具体的错误,下标需要数组或指针类型

 int sum = std::accumulate(contests.begin(), contests.end(), 0,
        [](const auto a, const auto b)->int {return a[0] + b[0]; }
    );

然后修复

int sum = std::accumulate(contests.begin(), contests.end(), 0,
        [](const auto a, const auto b)->int {return a + b[0]; }
    );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-13
    • 2021-04-11
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多