Niall Douglas wrote:
Ok, let me rewrite that so we know we are on the same page:
future<T>.next(R(T)) is the same effect as:
future<T>.then([](future<T> f){ return R(f.get()); // f.get() rethrows any exception, doesn't execute R(T) });
Something like this, if by R(T) you mean a function object taking T and returning an R, and by R(f.get()) you mean executing this function object with f.get() as an argument. But the implementation of .next will not need to rethrow on exception and will not need to execute any user code in this case, it just moves the exception_ptr into the future<T> returned by .next.
Your .next() is the same as Vicente's expected.bind() right?
My idea of .next was the same as his .map, but now that you bring it up, I'm not quite sure whether .bind won't be better.
If so, I was going to have .then() cope with a R(T) callable, but that requires metaprogramming to examine the input and determine the overload.
You're not going to be able to tell the difference between .then and .next when given [](auto x) { ... }.
I think I saw you didn't like Vicente's catch_error(E)? Was there a reason why? Is there anything wrong with a .next(R(E))?
It's not that I don't like it, I don't see sufficient motivation for it. I'm also not quite sure how it's to be used. Vicente's wording in N4048 is a bit unclear. future<X> f1 = async( ... ); future<Y> f2 = f1.catch_error( []( exception_ptr e ) { return Y(); } ); What happens when f1 has a value?