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 &operator()() {
static std::pair 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
struct unary_op {
typedef Result result_type;
F1 f_;
Input1 input1_;
const std::pair &operator() {
static std::pair 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
struct binary_op {
typedef Result result_type;
F2 f_;
Input1 input1_;
Input2 input2_;
const std::pair &operator() {
static std::pair 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 sqrt_stage(f2, sqrt);
binary_op add_stage(f1, sqrt_stage,
plus());
// 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 f1(file1);
file_reader 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(), // 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.