On 01/16/18 17:50, Niall Douglas via Boost wrote:
Given the above, unless LTO is used, I think the compiler will most often not be able to optimize the virtual function call.
As you noticed later in your reply, if a virtual function is marked final, the compiler inserts a check to see if the vtable's implementation matches and if so uses an inlined edition.
Being final has no effect if the final function declaration is not immediately visible to the compiler. The compiler optimization that I described is performed regardless of that markup.
Do I think this overhead is significant enough? Difficult to tell. Certainly I'm not happy about it, but I could probably live with the 1.5x overhead. However, it still results in code bloat and there is no guarantee this optimization will be performed by the compiler (or that it will be effective if e.g. my code always overrides `error_category::failure`). Thing is, every bit of overhead makes me more and more likely consider dropping `error_code` in favor of direct use of error codes. `error_code` already carries additional baggage of the pointer to error category.
You might be interested to learn that in a real world code base I tested, padding error_code's size to 64 bytes produced no statistically observable slowdown on Intel Ivy Bridge. As soon as it tipped over 64 bytes though, it became very noticeable, about 5%. That was for error_code_extended in Outcome v1, I wanted to see how much payload I could cram in there.
So when you say error_code comes with baggage over C error codes, I'll claim that you could in fact add lots more baggage still and probably see little effect.
Sure, what you call "significant overhead" depends on what you actually do. That's why there is no single answer to the question you asked in the initial message. But note that `error_code` is supposed to be the replacement for all kinds of error codes in the wild. There are APIs that use error codes with very simple, even trivial functions like setters or getters. If we are to claim `error_code` is suitable for those cases then it really should be very *very* close in costs to a simple `int` to be viable. So if it, for instance, cannot fit in a register to return efficiently then that's a problem. If it requires an indirect call to check for success, that's a problem too.