#include <vector>
#include <iostream>
#include <iterator>
#include <array>
using namespace std;

class Generator {
protected:
    vector<int> v;
public:
    Generator(unsigned length): v(length) {}
    
    template<class Outputter>
    void do_calculations_with_output(Outputter& out){
        // perform first part of some complex operations on v
        out.output(v);
        // perform second part of some complex operations on v
        out.output(v);
        // perform some final actions
    }

};

class SimpleDumpOutputter {
private:

    ostream* out;
    unsigned count;
public:
    SimpleDumpOutputter(ostream& os): out(&os), count() {}
    template<class C>
    void output(const C& c) {
        *out << "Step " << ++count << " of calculation: ";
        copy(c.begin(),c.end(), ostream_iterator<int>(*out, " "));
        *out << endl;
    }
};

class FancyOutputter {
    ostream* out;
    int count;
public:
    FancyOutputter(ostream& os): out(&os),count() {}
    template<class C>
    void output(const C& c) {
        // create a graph using graphviz's dot language to ease visualisation of v
        *out << "Step " << ++count << " of calculation: ";
       *out << "Graphviz output\n";
    }
};

template<class... Outputters> class AggregateOutputter : private Outputters... {
private:
   template<class First, class... Rest>
   struct output_helper{
      template<class C>
      static void do_output(AggregateOutputter* pthis,const C& c){
          static_cast<First*>(pthis)->output(c);
          output_helper<Rest...>::do_output(pthis,c);
      }

   };
    
   template<class First>
   struct output_helper<First>{
      template<class C>
      static void do_output(AggregateOutputter* pthis,const C& c){
          static_cast<First*>(pthis)->output(c);
      }

   };
public:
   template<class... Out>
    AggregateOutputter( Out&... out): Outputters(out)...{}
    template<class C>
    void output(const C& c) {
        output_helper<Outputters...>::do_output(this,c);
    }
 // first argument is dummy, because we would use the ostreams in destinations
};
int main(){

AggregateOutputter<FancyOutputter,SimpleDumpOutputter> out(cout,cout);

Generator g(10);

g.do_calculations_with_output(out);

}