
OK, here it is without leading ~s. It seems GPG inserts them for some strange reason when there is leading space on the line. David Abrahams wrote: | | I don't understand yet. What is the difference between stage_1 and | stage_2? Fewer arguments in stage_1? | exactly. e.g. stage reading from file: template<typename Result> struct file_reader { typedef Result result_type; istream f_; const std::pair<Result, bool> &operator()() { static std::pair<Result, bool> r; f_.read(&r.first, sizeof(Result)); r.second = f_; return r; } // some initialization stuff to set f_ }; stage calculating unary function on its input (and input is, of course, a stage): template<typename Result, typename F1, typename Input1> struct unary_op { typedef Result result_type; F1 f_; Input1 input1_; const std::pair<Result, bool> &operator() { static std::pair<Result, bool> r; typename Input1::result_type const &i1 = input1_(); r.first = f_(i1.first); r.second = i1.second; return r; } // some initialization to set input1_ and f_ }; stage adding its two inputs: template<typename Result, typename F2, typename Input1, typename Input2> struct binary_op { typedef Result result_type; F2 f_; Input1 input1_; Input2 input2_; const std::pair<Result, bool> &operator() { static std::pair<Result, bool> r; typename Input1::result_type const &i1 = input1_(); typename Input2::result_type const &i2 = input2_(); r.first = f_(i1.first, i2.first); r.second = i1.second && i2.second; return r; } // init to set i1_ and i2_ }; this would be the intended usage: // // reading input from 2 files, producing as result x + sqrt(y) // file_reader<double> f1(file1); file_reader<double> f2(file2); unary_op<double, ..fill in..> sqrt_stage(f2, sqrt); binary_op<double, ..fill in..> add_stage(f1, sqrt_stage, plus<double, double>()); // this loop would be another "stage" parametrized by the function // performing the actual work done in the body. while(1) { typename adder::result_type r = ad(); if(!r.second) break; // do something with the data } ultimately, would it be possible to write somehting like: file_reader<some_struct> f1(file1); file_reader<another_struct> f2(file2); // note the difference in structs! stages can convert types between // input and output // // do some template magic :) // stage_op( my_consumer_functor(), // obvious stage_op( // producer for the consumer plus<double, double>(), // operation to perform on two inputs f1, // provider for the first argument stage_op( sqrt<double>(), // function for this stage f2))) // provider for this stage If the outer stage_op(my_consumer_functor()..) is removed then I get a 'stream' from which I can extract individual element by calling operator() repeatedly. Please view this final use case as the thing I'm really trying to achieve. The example stage implementations might be on the totally wrong track. Something along current container/iterator[1]/algorithm/functor framework (no, I can't read the whole data set into memory :)), but which would work in a 'lazy' manner producing values on demand only. I believe this is called 'lazy evaluation' in some functional languages. Also I need to be able to define alternate stopping criterion (e.g. stop when ALL streams are exhausted, not the first one - this is useful for merging several streams into a single stream). [1] maybe just define new iterator classes? In the meantime I've read the Phoenix documentation and it seems I could achieve this with Phoenix. I might be mistaken. Tonight I'm writing my first prototype code. I'm open to all suggestions. Thanks in advance for all suggestions.