On 2/12/2016 2:48 PM, Emil Dotchevski wrote:
On Fri, Feb 12, 2016 at 1:25 AM, Michael Marcin
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).