#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>
#include <iterator>
using namespace std;
using namespace std::placeholders;

class sequence {

  vector<int> data;

  public:
    typedef vector<int>::const_iterator it;

    // add
    sequence& operator<<(int rhs) { 
      data.push_back(rhs);
      return *this;
    }

    // reduce
    sequence& operator<<(function<int(int,int)> binary_op) {
      if (data.size() > 1) {
        const int result = accumulate (data.begin()+1, data.end(), *data.begin(), binary_op);
        data.clear();
        data.push_back (result);
      }
      return *this;
    }

    // map
    sequence& operator<<(function<int(int)> unary_op) {
      transform(data.begin(), data.end(), data.begin(), unary_op);      
      return *this;
    }

    // manipulate
    sequence& operator<<(function<void(vector<int>::const_iterator begin, vector<int>::const_iterator end)> manip) {
      manip (data.begin(), data.end());
      return *this;
    }
};

// functional objects
auto sum = plus<int>();
auto prod = multiplies<int>();

// template functor
struct out {
  ostream& os_;
  out (ostream& os) : os_(os) {}

  template <typename Iterator>
  void operator ()(Iterator begin, Iterator end) {
    copy (begin, end, ostream_iterator<typename Iterator::value_type>(os_," "));  
    os_ << endl;
  }
};

auto out_cout=out(cout);

// lambda
auto change_sign = [](int x)->int { return -x; };

// function
int sqr (int x) { return x*x; }

int main() {
	sequence seq;
    seq << 1 << 2 << 3 << out_cout 
        << sum << out_cout
        << 4 << 5 << prod << out_cout
        << 2 << sqr << out_cout
        << -42 << change_sign << out_cout;
}
