|
Boost Users : |
From: Zeljko Vrba (zvrba_at_[hidden])
Date: 2005-07-04 21:22:02
-----BEGIN PGP SIGNED MESSAGE-----
Hash: RIPEMD160
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.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (FreeBSD)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org
iD8DBQFCye7KFtofFpCIfhMRA+I6AJsGCYmzftPKwYQfolrbryxNbPyMCQCfZo1E
c+qqZL0QV4qaSlKlpV5jsXE=
=O9qT
-----END PGP SIGNATURE-----
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net