Hello everyone,
I've been meaning to learn to use Boost.Proto for quite some time and
I've finally started getting my hands dirty in code ever since that
fantastic video from BoostCon 2010. After the usual exercises that are
presented in it and the docs, I've set up my own goal of trying to write
composable futures (something that I think quite a lot of people have
been doing in their own time).
You can see the code at http://pastebin.com/DW4LckMP and I'd welcome
comments on what I've been doing wrong and how I could improve the
design. I also welcome answers to my following questions:
* regarding copying, the docs present the following example:
auto sum = boost::proto::lit(1) + 2;
here, since the 1 is held by a reference which will outlive (in the
variable sum) the actual literal expression (in the call to proto::lit)
we will have UB.
To avoid this exact problem, and since Boost.Proto is not move aware and
std::future is move-only, my terminals are actually of the form:
future_expresionstd::future&::type>
(where future_expression is the expression wrapper). Can I do this?
Obviously I still have a problem if I do:
std::future<int> fint = ...
auto sum = ns::compose(fint) + 3;
// then use sum.get()
don't I? I can't solve it by using proto::deep_copy since std::future is
move-only (apparently my terminals get stripped of their reference).
This means that the 'correct' way of doing the above would be
std::future<int> fint = ...
auto const operand = 3;
auto sum = ns::compose(fint) + operand;
// use sum.get()
thus separating lifetimes from computations (expression trees, really).
* the following doesn't compile:
struct local {
int method() { return 1; }
int method() const { return 2; }
};
auto method = (int (local::*)()) &local::method;
auto cmethod = (int (local::*)() const) &local::method;
auto f1 = std::async([] { return local(); });
auto f2 = std::async([] { return local(); });
auto r1 = (ns::compose(f1)->*cmethod)(); // this line OK
auto r2 = (ns::compose(f2)->*method)(); // Not OK!
assert( r1.get() == 2 && r2.get() == 1 );
( you can replace the above in main() instead of the previous )
Apparently the problem is an attempt to convert a pointer to const local
to a pointer to non-const local. Invoking cmethod instead (with the
appropriate assertion) is fine. I've checked that the result of
ns::compose(f1).get() is indeed a local and not a const local via
static_assert. This is using Boost 1.42. Any idea?