【问题标题】:Using std::accumulate使用 std::accumulate
【发布时间】:2011-03-01 18:15:15
【问题描述】:

我总是尽可能地尝试结合 STL 算法,而不是编写手动循环。但是,我很难理解std::accumulate 通常是如何有用的。每当我需要计算总和或平均值时,我几乎总是求助于手动循环,因为我很难让std::accumulate 做我需要的事情。

问题是我很少有需要求和的简单整数向量。通常,我想使用特定的成员变量对对象数组求和。是的,我知道std::accumulate 有一个版本,它采用BinaryFunction,但我看到的问题是这个函数需要采用T 类型的两个值,其中Tsum 的类型,而不是操作数的类型。我无法理解这有什么用处。

考虑一个我认为很常见的案例。我有以下课程:

struct Foo
{
    Foo(int cost_, int id_) : cost(cost_), id(id_)
    { }

    int cost;
    int id;
};

现在,假设我想使用 Foo::cost 计算 Foo 对象数组的总和。

我想说:

std::vector<Foo> vec;
// fill vector with values
int total_cost = std::accumulate(vec.begin(), vec.end(), 0, sum_cost);

sum_cost定义为:

int sum_cost(const Foo& f1, const Foo& f2)
{
    return f1.cost + f2.cost;
}

问题是,这不起作用,因为std::accumulate 需要一个 BinaryFunction,它接受 resulting sum 类型的两个实例 - 在本例中只是 int。但这对我有什么用?如果我的 BinaryFunction 接受两个 ints,我不能指定我想对 cost 字段求和。

那么,为什么std::accumulate 会这样设计呢?我只是在这里没有看到明显的东西吗?

【问题讨论】:

  • 如果你的类表示的是可以累加的对象,可以考虑加+和+=操作符。
  • Nitpick:std::accumulate 需要一个 BinaryFunction,而不是 BinaryPredicate。谓词返回一个布尔值。

标签: c++ c++11 stl


【解决方案1】:

你错了,累积运算符采用两个相同的类型。只有您愿意,它才会这样做。运算符的使用具体为sum = op(sum, *iter)。因此你的代码:

int count = std::accumulate(stuff.begin(), stuff.end(), 0, [](int current_sum, stuff_value_t const& value) { return current_sum + value.member; });

如果您不能使用 lambda,那么您当然可以使用标准绑定器或 boost::bind。

【讨论】:

  • 他没有标记这个c++0x,所以你对 lambda 的使用没有多大用处。
  • 嗯,你是对的。我似乎从here 那里得到了不好的信息,上面写着“二进制运算以 T 类型的两个元素作为参数,并返回累加运算的结果。”
  • @Channel - 是的。这个来源是错误的。
【解决方案2】:

使用函子:

class F { // sum Foos
    F(int init = 0);
    template<class T>
    Foo operator()(const Foo &a, const T &b) const;
    operator int() const;
};

int total_cost = std::accumulate(vec.begin(), vec.end(), F(0), F());

注意你也可以做其他事情:

class F { // sum foo values members
    template<class T>
    T operator()(const T &a, const Foo &b) const;
};
int total_cost = std::accumulate(vec.begin(), vec.end(), int(0), F());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多