Many thanks to those who have contributed to the discussion in the other
thread regarding making a breaking change to Boost.System in order to
provide empirical test data to persuade WG21 to similarly break
in a future C++ standard for its own good. This fresh
email is hopefully to start finishing the discussion.
To summarise discussion to date, Peter has made Boost.System's
error_code and error_category constexpr except for the virtual
functions. A big win for codegen, and the choice of the default
constructor of error_code to use system_category now no longer prevents
constexpr, so the request for a new special null_category() can also be
dropped. There is substantial opposition to making message() return
string_view, so let's drop that request.
That leaves the request to fix "if(ec) ..." which right now returns true
if the value is 0, despite that much code writes "if(ec) ..." to mean
"if error then ...". There is also the issue of error coding schemes not
being able to have more than one success value, which usually must be 0.
That's the remaining discussion point.
Myself and Peter feel this is worth fixing despite the increased runtime
overhead. Others, including one of its original inventors, feel it is
too much overhead. To add some empirical evidence to the discussion, I
have coded up a mock up of the improved error_code which can be viewed
at https://godbolt.org/g/dDAWih. This demonstrates constexpr error_code
and error_category in action as well.
To summarise what the mock up demonstrates:
1. error_category() gains a new virtual function called `bool
failure(int code)` which is now called by error_code's operator bool.
2. Thanks to the new constexpr construction, the compiler now completely
elides from runtime the case where an inlined function returns an error
code and the caller acts upon it. As in, **zero code is now generated**.
Far better than before. No virtual functions are called, they are
optimised out entirely.
3. For unknown error codes from extern sources where the linker is
generating an executable, the "final" modifier removes a layer of
indirection when calling `failure()` after the linker has run, and
indeed clang seems to go ahead and inline the implementation entirely
despite us not asking for LTO. Which is kinda cool.
4. Thus only in shared objects, and only for unknown error codes from
extern sources, is a virtual function call actually performed. And given
the frequency of doing `if(ec) ...`, it'll almost certainly be hot in
the branch predictor i.e. no stalls.
Question: is this still considered too much overhead? Note that there is
no longer ANY proposed breaking change with existing code. This is now
100% enhancement only.
Niall
--
ned Productions Limited Consulting
http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/