On 04/27/2013 03:30 PM, Vicente J. Botet Escriba wrote:
Le 27/04/13 09:39, Pierre T. a écrit :
On 04/26/2013 08:17 PM, Vicente J. Botet Escriba wrote:
Le 26/04/13 14:22, Pierre T. a écrit :
Hello,
I wrote a proposal for the Boost.Expected project. You can find a pdf version here:
http://hyc.io/boost/boost-expected-proposal.pdf
It's about the Boost.Expected project, I'll add my own informations by the end of the week.
Finally, I propose a single class design, and facilities for custom error code. It's based on the Alexendrescu idea upgraded by Vicente J. Botet Escriba and myself. I also took into account the Boost.Optional class. If needed for this proposal, I can add documentation per method (such as in official proposal), but I'm not sure it's useful without a frozen interface.
Please do not hesitate to comment it and request further clarification,
Hi,
first of all, thanks for writing this proposal.
I have some concerns
* Single class: I'm all for a single class; but having an ExceptionalType template parameter which defaults to exception_ptr.
template
class expected; We could define the traits that make the difference between having an exception_ptr and another error
With these traits we are able to define the functions that have a specific behavior as e.g.
I like this proposition but at first, it seems a bit "overkill". I would like to have more opinions about it. Through it seems to be less compatible with the "visitor" idea. The visitor resolves on types and most of the error code have a same type. So it would visit only one type. Right. But this independent on whether you use a wrapper exception or not, isn't it? Yes, it gives a good point to the traits.
* Default Constructor or constructor from nullexpect What is the advantage of having a expected instance that doesn't have neither a value nor an exception? How would the user manages with this possibility? Are you looking to make expect movable?
Basically, I noticed that classes without default constructor (or default state) are burdensome to use. Indeed, you cannot store an expected in a class as a member if not initialized in the constructor. Or doing something like:
expected<int> e; if(…) else(…) return e;
Through, I removed the default constructor because I found it unclear. I use a nullexcept because it was a good idea in Boost.Optional with nullopt. Yes it was one. But the definition of optional is there to allow a state that means value not present. expected<> is designed to have a value or an exception. Could you answer to the question How would the user manages with this possibility? By testing == nullexcept (operator== not in the proposal, sorry), however you are right, expected must contains an exception or a value. On the other hand, it's nice to provide a default constructor, so an idea could be to add a method "unitialized_error()" in the trait class.
Finally, I'm not sure to understand how it's related to the movable ability of Boost.Expected. I let you try to define move move semantics for expected and you will see why this is related.
* then/otherwise issues
Humm, I don't agree here with the proposed design (even if I made the then suggestion). What returns the then function if the instance has a value? I declared it as
template <typename F> expected
::type> then(F&& fuct) Let me name typedef typename boost::result_of
so the result would return the expected<RT>(fuct(value_)). Chaining this temporary with an otherwise call will work with the new temporary, and not with the original expected. I don't think this was what was expected ;-)
E.g.
string f(int); int f(string);
expected<int> e= 1; e.then(f).otherwise(g);
Here g will be called with expected<string>(fuct(value_)).except_. Hrrr
expected<int> e= make_exceptional_expect(X); e.then(f).otherwise(g);
Here g will be called with the exception_ptr stored in e. Hrrr
That is g don't know if it is called with an exception stored on e or on the temporary resulting for the call to f.
But the design error is not on the otherwise function but on the then function.
Resuming, I'm not more for the 'then' function.
I'm totally agree with you. But I think that I misnamed the "otherwise" method. I think the "then" method is really useful, it's like an automaton. With e.then().then().then(), the treatment is stopped anytime when an error occurs in a then method. How would this be stopped? throwing and exception? It's not stopped but the "then" method launch the function only if expected contains a value. Also, I think that the function taken by then should return void And which value would you pass to the second then call? The same. or an expected.
In fact the otherwise method is the error visitor. A common usage would be to chain it in the end:
e.then(...).then(...).then(...).visit_error(error_visitor);
visit_error is called if any "then" return an error. I found it wonderfully useful. This could be possible; It would need that then() returns an expression template storing all the functions on the chain and only
Maybe. But if we don't know how it is stopped chaining them has no sens. When the call to the function is asynchronous it is easy to stop it but synchronously it implies an exception which is against the goal of expected. the call to the visit_error would evaluate the chain. I don't think it is worth proving this lazy evaluation. To complete what I've said, the visit_error() would launch the visitor only if the expected contains an error. No lazy evaluation is needed.
Using a visitor would as you proposed initially would be better.
template <class V> void accept_visitor(V& visitor) const BOOST_NOEXCEPT { if (valid()) visitor.visit(value_); else visitor.visit(expectional, except_); }
I'm not sure that we should use the visitor pattern for the value and the error. Initially, I though at the visitor pattern because error would be exception-based, so with some types to visit. And also to provide a way to visit exception without throwing them with the get() method.
Well I let you think a little bit more about. The visitor is your idea. From my side I don't need it for the case where the Error is not an exception_ptr.
As usual, these discussions help a lot, but this time, I'm not sure if our idea are still good ideas, that's why more opinions would help.
Yes, it always helps to know what others think about. Very often people has no time to, or would not take the time until you present a concrete proposal and implementation so they can play with. If you send your application, I'm sure that other mentors would comment on the subject you could request to them.
I'll try to send it before tomorrow. I will update it with the trait classes and the others comments you made. I just have a question about the proposal, should I use the Boost macro for noexcept,… or is it better (for a proposal) to write it with the standard tools ?
Best, Vicente
Thanks again for these comments, Pierre T.