$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] [err] RFC
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2015-11-18 18:43:47
Le 18/11/2015 06:49, Gavin Lambert a écrit :
> On 17/11/2015 21:06, Domagoj Saric wrote:
>>>> Also, if the fallible_result rvalue is left uninspected and 
>>>> contains an
>>>> error its destructor will throw (which AFAICT should be safe 
>>>> considering
>>>> it is an rvalue and no other exception can possibly be active at the
>>>> same time)
>>>
>>> Throwing from a destructor can cause abrupt termination (or undefined
>>> behaviour in some compilers); there are no conditions in which it 
>>> should
>>> be considered "safe".
>>
>> That's not mandated by the standard...that would be a broken
>> compiler/standard library...
>
> It's mandated by the standard if another exception is already in flight.
>
>>> Additionally I'm not convinced that no exception can be active at the
>>> same time.  Consider function call parameters -- you could easily have
>>> one of these get constructed but not consumed yet, and then another
>>> parameter throws an exception, resulting in destruction of your object
>>> during the throw of an exception.
>>
>> That can't happen: fallible_results are not meant for passing
>> parameters, and thanks to the rvalue semantics this is enforced by the
>> compiler rather than just by convention - even if you go to some lengths
>> to declare a function as taking a fallible_result (i.e. completely
>> contrary to what the type is for)
>> foo( fallible_result<bar_t> bar ); (instead of foo( bar ); )
>> you'll soon discover that you are doing something wrong because the
>> compiler won't let you do anything with that bar...
>> (and if the standard would let me declare a special && destructor for
>> rvalues there'd be no end to happiness, i.e. you'd get an error
>> immediately, at the declaration, and even better codegen in 
>> somecases...)
>
> Declaring a parameter as fallible_result<T>&& will satisfy the 
> compiler, and this doesn't seem unreasonable if it's being passed to a 
> helper method intended to process such results.
>
> Imagine a function that calculates several results, some of which may 
> fail, and then calls a combiner method to choose the "best" 
> non-failing result of the set.  Wouldn't the combiner naturally expect 
> a fallible_result<T>&& as its inputs, since it wants to consume them?
>
> I suppose you could force it to accept result_or_error<T> instead, but 
> since this isn't the return type of the function it inhibits using 
> generic type-deducing template code with simplified expressions like:
>    return combiner(calcA(), calcB(), calcC());
>
> The more problematic case is if the combiner was not expecting 
> failure, and so someone used the same expression with a combiner that 
> accepted T.  So the compiler calls all three calc methods 
> (constructing fallible_result<T>s along the way), then gets around to 
> converting the first one back to T, which throws.  This is ok, but 
> then the other two are destroyed; and if at least one of these throws 
> too, then you're dead.
>
> Sure, you can tell people to only use this as a standalone expression 
> and not as a function parameter, but this seems very fragile.  People 
> like to inline things, especially rvalues.
>
Your example can be adapted to several variables of type faillible_result<T>
auto a = calcA();
auto b = calcB();
auto c = calcC();
if (a.value()) // can throw :(
I like the intent of faillible_result<T>, but as you described it could 
be more dangerous than safe.
Thanks for reporting this case. It helps me a lot.
Vicente