On 01/13/18 02:58, Niall Douglas wrote:
1. Stop treating code zero as always meaning success irrespective of
category. This remedies a defect where some custom error code domains
cannot be represented by error_code due to using value 0 for an error.
In actual code, I've never seen anyone ever use comparison to anything
but a default constructed error code, so I think this will be safe.
In my code I'm using contextual conversion to bool extensively, e.g. "if
(err)" or "if (!err)". This is currently equivalent to comparing against
0, so I assume it will be broken by this change. So, you can count me
right now as the one (loudly) complaining, among many others, I think.
Sorry, I forgot to mention that the category would be asked whether the
error code's current value is success or failure <snip>,
This is unavoidable because system_category (on POSIX and Win32) and
generic_category both define value = 0 as success. In some other error
code domain, -1 might mean success. Or 9999. Up to the domain. No
requirement that 0 be set aside as special, as currently.
On Sat, Jan 13, 2018 at 6:09 AM, Andrey Semashev via Boost <
boost@lists.boost.org> wrote:
I appreciate that the special meaning of 0 may be undesirable, but having
a virtual function call overhead whenever one wants to test if the
error_code has a success value seems a too high price for that. I don't
want to be paying that price in my Linux programs, sorry.
My understanding is that the current design explicitly
enables many-to-many comparison of ("error-")values across error domains
(error categories).
Specifically, the implication is that there are "many" success-values; or
"many" success-values specific to a given application-specific context.
We've already had recent threads discussing how to handle the several "HTTP
2xx" return-values as all indicating "success", but none of them are of
value "zero". (Answer: Case out the 'enum' values, or compare to a
generic 'success' enum-value designed for that purpose.)
So, we can discuss the "trap-value" of zero as meaning something, but it
seems real-world algorithms must handle these multiple success-values
(whether or not we want to expect a 'zero' as meaning something in
particular).
If we concede that many 'success' values exist, the class of
'std::error_code' values becomes:
(a) empty, (e.g., default-ctor)
(b) success (many possible values, context-determined)
(c) error (many possible values, context-determined)
Of course, some "errors" are fatal, and some are not. Does a non-fatal
error become a warning? Must we explode the above list (quoting 'syslog')
to: "emerg", "alert", "crit", "err", "warning", "notice", "info", "debug"
...?
My guess is that there is no appetite for greater granularity. Regarding
"less" granularity, there are two classes of 'std::error_code' values:
(a) empty (e.g., default-ctor)
(b) non-empty (an application filled-it-in with something, which may
represent 'success' or 'failure')
...At which point, the caller receiving the 'std::error_code' instance must
interrogate by comparing against an 'enum' (to determine some form of
"success" or "failure"). This is the genius of the current-design, where
the "heavy-lifting" of the many-to-many cross-domain mapping is done by
one-or-more library authors that sensibly map those codes, and present the
user with a manageable and discrete set of enums against which the
'std::error_code' value may be tested.
IMHO, the 'if(ec)...' is a problematic construct if it is to imply some
form of "success". It seems more suited to imply "no-value-populated"; but
I think that is a very limited test that probably isn't very helpful in the
real-world: If the caller receives the value from some implementation, the
caller can trust it to represent something and doesn't care about the
distinction between "empty" and "not-empty", but only between "success" and
"not-success".
The current design mandates that the caller must handle the
several forms of success that may be provided by the implementation, and
the 'if(ec)' construct cannot do that: Only enum-testing can do that,
where the 'enum' provides the context against which the test can be
evaluated. But, I concede that people are using the 'if(ec)' now, to test
for 'success', which behaves correctly in those cases where the
implementation provides an "empty" value indicating "success".
My opinion is that there is a single category of 'std::error_code' values:
(a) something-or-nothing
...whereby an application must interrogate with an 'enum', which is the
process of collapsing many-values (possibly across domains) for a boolean
result, like one of::
if(ec == BADNESS_MUST_ABORT)
...
if(ec == IS_OK_CAN_PROCEED)
...
--charley