Boost logo

Boost :

Subject: Re: [boost] expected/result/etc
From: Michael Marcin (mike.marcin_at_[hidden])
Date: 2016-02-13 00:02:28


On 2/12/2016 2:48 PM, Emil Dotchevski wrote:
> On Fri, Feb 12, 2016 at 1:25 AM, Michael Marcin <mike.marcin_at_[hidden]>
> wrote:
>>
>> If .get() isn't specified as UB when a value is not ready how are you
>> going to avoid the overhead?
>>
>> Specifically .get() must do *at least* an if statement before returning
>> the value.
>>
>
> Calling shared_ptr::get() is always well defined. It contains no ifs.
>

Okay. I don't see how that's relevant at all.

>>>
>> Sorry I don't follow.
>> Are you suggesting that the raytracer should be inlined into every call
>> site?
>>
>
> I avoid using inline except if the profiler tells me it's needed. If it is
> needed, then I inline regardless of whether the function emits exceptions
> or not.
>

Let me be more explicit.

You certainly wouldn't inline a raytracer (a heavy operation) at every
call site, you would just horribly bloat your executable for no benefit
and likely achieve a degradation of performance.

However the premise is that the code can have errors in cases which are
not unexpected (aka exceptional), which are not the result of
programming errors (logic errors), which occur because of limits
specifically put in place to constrain time and memory consumption of
the operation (performance is important even in the error control flow).

Note also that this is just an example, there are many other similar
scenarios that could be explored instead.

>
>> What I think you're saying is that where I want to write code that looks
>> like:
>>
>>
>> result<int> bar()
>> {
>> return std::make_error_code( std::errc::bad_address );
>> }
>>
>> int main()
>> {
>> int foo;
>>
>> auto _foo = bar();
>> if ( _foo ) {
>> foo = _foo.get();
>> } else {
>> foo = 0;
>> }
>>
>> return foo;
>> }
>>
>>
>> I should instead write code that looks like:
>>
>> int bar()
>> {
>> throw std::system_error(
>> std::make_error_code( std::errc::bad_address ) );
>> }
>>
>> int main()
>> {
>> int foo;
>>
>> try {
>> foo = bar();
>> }
>> catch ( std::system_error& e )
>> {
>> foo = 0;
>> }
>>
>> return foo;
>> }
>>
>>
>> And I should expect equal performance?
>>
>
> Obviously not, because you're always throwing. Throw may incur overhead,
> certainly does on Windows. What I'm saying is that when you don't actually
> throw, exception handling overhead occurs exactly where function call
> overhead occurs, and can be eliminated completely by inlining.

I thought it was obvious that that code is trying to illustrate a
difference in interface. Obviously bar() is meant to do work that
returns an int but sometimes can't and results in an error.

If you're going to choose exceptions to report your errors you're not
going to be able to avoid actually throwing because errors *will* occur
(as that is the whole premise of this thread).


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