Boost logo

Boost :

Subject: Re: [boost] [gsoc-2013] Boost.Expected
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2013-04-28 13:30:50


Le 28/04/13 18:27, Pierre T. a écrit :
> On 04/28/2013 05:20 PM, Vicente J. Botet Escriba wrote:
>> Le 28/04/13 16:22, Pierre T. a écrit :
>>> 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:
>>>>>> * 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.
>> Why do you need a default constructor.
> Because it can be useful for the following situation:
>
> expected<T> func(bool b)
> {
> expected<T> e;
> if(b)
> {
> e = f();
> // use e
> }
> else
> {
> e = g();
> // use e
> }
> return e;
> }
>
> Some programmers prefer to have only one return statement instead of
> having:
>
> expected<T> func(bool b)
> {
> if(b)
> {
> expected<T> e = f();
> // use e
> return e;
> }
> else
> {
> expected<T> e = g();
> // use e
> return e;
> }
> }
>
Humm, I don't know if this is enough.
>>>>>
>>>>> 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.
>> After thinking more on this the moved object could present its
>> exception_ptr if it has one, so move semantics doesn't force to have
>> an uninitialized expected<>
> Not sure to get it,
>
> expected(expected&& e) // nothing in the initializer list because we
> don't know if we must move T or Error.
> {
> if(has_value)
> // move value
> else
> // move error
> }
>
> In case T or Error haven't a default constructor, the previous code
> can't work, right ?
You would need to move construct using placement new

          new (&value_) T(forward<T>(val)) ;

BTW, exception_ptr move is equivalent to a copy, isn't it?

> Could we add a dummy field in the union such as:
>
> union{ T value, Error error, bool internal_uninitialized};
I don't think this is a good ideea.
>
> But I'm not sure it's what you meant.
>>>>>
>>>>>> *Ah I think I see now what was the initial intention. I suspect
>>>>>> that you mean that as the result of e.then(f) would transport the
>>>>>> exception stored on e if e is not valid, then the exception would
>>>>>> be relayed until there is a call to visit_error and no call to
>>>>>> any function will be done.
>> Yes this is quite similar if we had exceptions and we had a try/catch
>> block
>>
>> f0().then(f1).then(f2).then(f3).visit_error(error_visitor);
>>
>> try {
>> f3(f2(f1(f0())));
>> } catch(...) {
>> error_visitor();
>> }
>>
>> It would be great if we could have the equivalent for
>> try {
>> h(f(), g());
>> } catch(...) {
>> error_visitor();
>> }
>>
>> when_all(f(), g()).then(h).visit_error(error_visitor);
>>
>> when_all could return a expected<tuple<T1, T2>> or something more
>> specific so that then would extract the members of the tuple to call
>> h with two parameters.
>>
>> This start to look more and more like the proposal for futures
>> (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3558.pdf)
>>
> Sorry for the poor explanations about it, but you guessed correctly. I
> read the futures proposal and the ideas in there are really
> interesting. However because expected is not related to the time, I
> think we could just do the following:
>
> e.then(f, g).then(h).inspect(error_inspector)
>
> where "then" takes an unlimited number of functions. In this case it
> would return a tuple-wrapper class specific to the expected class (in
> case users would like to store tuple inside expected).
Humm, in the example I gave above f an g are not continuations but
expected<> producers.
Anyway, the variadic version of then could have its uses. I like it, but
it is orthogonal to the when_all feature.

What do you think about letting the continuation returning an
expected<>? It has the advantage to allowing the continuation to
transport exceptions also without throwing.

> About the "inspect" method, I try to find another name instead of
> visit_error because it makes me think to the pattern visitor which is
> too specific to hierarchy classes. I found that inspect was nice
> because it's like in a factory where the chief "inspects" that
> everything has been alright.
>
The name should work independently of the name of the 'then()' function.

on_exception? if_exception? catch_all? capture?

e.catch_all(eh);

And maybe catching/capturing an exception type at a time.

e.catch_one<E1>(e1).catch_one<E2>(e2).catch_all<EA>(eh);

e.capture<E1>(e1).capture<E2>(e2).capture<all>(eh);

But a C++ try/catch is not worst, or is it?

try { v=e.get(); } catch(E1 & ex) { e1(ex); } catch(E2 & ex) { e2(ex); }
catch(...) {}

Best,
Vicente


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk