2

我正在阅读以下问题: 如何总结 C++ 向量的元素?,我想使用第二种方法(sum_of_elems =std::accumulate(vector.begin(),vector.end(),0);//#include <numeric>)。

但是,我没有std::vector<int>,但是std::vector<struct packet>packet定义如下:

struct packet {
    /// ...
    int length() const;
    ///
}

我想要数据包长度的总和。

这是我尝试过的:

std::vector<packet> packets;
...
std::accumulate(packets.begin(), packets.end(), 0, [](const packet& a, const packet& b){return a.length() + b.length();});

但它不起作用。在 C# 中,我会写类似

packet[] p;
p.Select(x => p.length()).Sum();

有可能在 C++ 中做类似的事情吗?我可以编写方法来遍历向量并自己完成,但我更喜欢函数式方法。

4

5 回答 5

4

我会注意到 C# 实现在本质上略有不同。

在 C++ 中,您尝试添加intpacket而在 C# 中,您首先提供从packetto的转换步骤int,然后添加ints。

等价的 C++,没有改编:

std::vector<size_t> lengths; // a length cannot be negative!

std::transform(packets.begin(),
               packets.end(),
               backward_inserter(lengths),
               [](packet const& p) { return p.length(); });

auto const sum = std::accumulate(lengths.begin(), lengths.end(), 0ul);

当然,存储中间长度是浪费的,但是它确实可以开箱即用。

但是因为我们很酷,让我们看看Boost.Range,更准确地说:

像 Linq 一样有点酷:

#include <boost/range/numeric.hpp> // accumulate
#include <boost/range/adaptor/transformed.hpp>

size_t total_size(std::vector<packet> const& packets) {
    return boost::accumulate(
        packets | boost::transformed([](packet const& p) { return p.length(); }),
        0ul);
}
于 2013-08-15T13:19:30.590 回答
3

您正在通过二进制操作进行累积。您的累积值以0(an int) 开头,因此二进制操作的左侧必须是可转换的0- 否则,它如何开始添加?

尝试这个:

std::accumulate(
  packets.begin(),
  packets.end(),
  0,
  [](int a, const packet& b){
    return a + b.length();
  }
);

你也可以通过一个简单的循环来做到这一点:

int acc = 0;
for( const packet& p : packets ) {
  acc += packets.length();
}
于 2013-08-15T13:09:06.903 回答
2

累加操作的第一个参数是运行总计。在你的情况下,这是一个整数,而不是一个数据包,所以你的 lambda 应该是

[](int a, const packet& b) {return a + b.length();}
于 2013-08-15T13:09:48.293 回答
1

问题是您的累积功能。它的第一个参数必须是您尝试累积的类型(int在这种情况下)并在其上添加一个值。

您的 lambda 函数应如下所示:[](int currTotal, const packet& b){return currTotal + b.length();}

于 2013-08-15T13:09:17.107 回答
1

除了lamba,您可以将其更改为

std::accumulate(packets.begin(), packets.end(), 0, packet());

您可以将仿函数定义为:

int operator() (int result, const packet& obj)
{
    return result+ obj.length();
}
于 2013-08-15T13:10:51.053 回答