使用 std::accumulate 累积到 std::ostream

Accumulating into std::ostream using std::accumulate

我正在尝试使用 std::accumulate 写入 operator<< 中的 std::ostream(这只是一个最小的示例,我知道这可以更简单地实现):

#include <iterator>
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>

struct A {
    A() : v(std::vector<int>()){};
    std::vector<int> v;
    A(std::vector<int> v) : v(v){};
    friend std::ostream& operator<<(std::ostream& stream, A& a);
};

std::ostream& operator<<(std::ostream& stream, A& a) {
// I need something similar to
//    return std::accumulate(a.v.begin(), a.v.end(), "",
                           std::ostream_iterator<int>(stream, " "));
// or:
// return std::accumulate(a.v.begin(), a.v.end(), stream,
                           []()->{});
}

int main(int argc, char* argv[]) {
    std::vector<int> v({1, 2, 3, 4, 5});
    A a(v);
    std::cout << a << std::endl;

    return 0;
}

我怎样才能让这个运算符工作?

不要使用accumulate,使用copy:

std::ostream& operator<<(std::ostream& stream, A& a) {
  std::copy(a.v.begin(), a.v.end(), std::ostream_iterator<int>(stream, " "));
}

这实际上是 one of the examples at the above reference page(虽然 std::copy,而不是 std::ostream_iterator

既然你提到 for_each 也可以使用(刚才提到 accumulate 是为了混淆火星人):

std::ostream& operator<<(std::ostream& stream, const A& a) {
  std::for_each(begin(a.v), end(a.v), [](int i){ std::cout << i << " "; });
  return stream;
}

注意:此处会有尾随 space。如果你想避免这种情况(例如通过在 lambda 中使用计数器),你需要以不同的方式处理第一个或最后一个元素。

可以做到:

// Using accumulate
std::ostream& out_acc(const std::vector<int>& is, std::ostream& out)
{
    return std::accumulate(is.begin(),
                           is.end(),
                           std::ref(out),
                           [](std::ostream& os, int i) -> std::ostream&
                           { return os << i << ", "; });

}

// Using for_each
std::ostream& out_for(const std::vector<int>& is, std::ostream& out)
{
    std::for_each(is.begin(),
                    is.end(),
                    [&](int i)
                    { out << i << ", "; });
    return out;

}

for_each 是自然的选择,因为你不太关心累积值。

您可能会像这样滥用 std::accumulate

std::ostream& operator<<(std::ostream& stream, A& a) {
    return std::accumulate(a.v.begin(), a.v.end(), std::ref(stream),
                           [](std::ostream& stream, int e)
                           { return std::ref(stream << " " << e); });
}

Demo