代码之家  ›  专栏  ›  技术社区  ›  anon

使用std::累加累加到std::ostream

  •  0
  • anon  · 技术社区  · 10 年前

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

    #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;
    }
    

    我如何让这个操作员工作?

    4 回复  |  直到 10 年前
        1
  •  2
  •   ecatmur    10 年前

    不要使用 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 .

        2
  •  2
  •   Jarod42    10 年前

    你可能会滥用 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

        3
  •  0
  •   molbdnilo    10 年前

    可以这样做:

    // 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 是自然的选择,因为你并不太在意累积价值。

        4
  •  0
  •   Rumburak    10 年前

    既然你提到了 for_each 也可以使用(刚刚提到的积累是为了迷惑火星人):

    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;
    }
    

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