$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] [err] RFC
From: Domagoj Å ariÄ (dsaritz_at_[hidden])
Date: 2015-11-19 10:58:34
On Wed, 18 Nov 2015 11:19:30 +0530, Gavin Lambert <gavinl_at_[hidden]>  
wrote:
>>> 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.
I thought you meant in the general case as you separately mentioned the  
case of 'active exceptions' in the following paragraph...so I'll address  
this there...
>>> 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,
Actually, due to that new dark corner of the language (still somewhat dark  
to me too) called 'reference collapsing rules', that won't make much of a  
difference: even if you capture/bind an rvalue to a && it is no longer an  
rvalue (my 'non formal' understanding) and && member function overloads  
can only be called on rvalues...
> and this doesn't seem unreasonable if it's being passed to a helper  
> method intended to process such results.
Helper methods are supposed to know the semantics of types they work for?
> 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?
No, as you say below it should expect result_or_error, the documented type  
to be used for 'saved' (i.e. to be inspected after the expression that  
generated them) results...
> 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());
It inhibits it no more than the addition of other wrappers, like smart  
pointers or optionals, does...
These are usually handled with 'interface normalization' global functions  
like get_ptr()...likewise boost::err could add get_result(),  
get_result_or_error(), has_result(), has_succeeded() or others along those  
lines...
> 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.
As explained before this cannot happen as even the implicit conversion  
operators work only on rvalues...
> 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.
AFAICT I think I've answered the, so far laid out 'fragility' objections...
-- "What Huxley teaches is that in the age of advanced technology, spiritual devastation is more likely to come from an enemy with a smiling face than from one whose countenance exudes suspicion and hate." Neil Postman