Boost logo

Boost :

Subject: Re: [boost] Noexcept
From: charleyb123 . (charleyb123_at_[hidden])
Date: 2017-06-13 22:07:22

> > Emil Dotchevski wrote:
> >
> >> If error codes are treated as "the error", then the error domain is
> >> limited to a single function. Consider these two functions:
> >>
> >> int f1(....); //returns 0 on success, 1-f1_error1, 2-f1_error2
> >> int f2(....); //returns 0 on success, 1-f2_error1, 2-f2_error2
> >>
> >> If f2 calls f1, if the error is communicated by an error code, f2 _must_
> >> translate the error condition from the domain of f1 errors, to the
> domain
> >> of f2 errors. And this must be done at every level, which introduces
> many
> >> points in the code where subtle errors may occur, and that is in error
> >> handling code which is very difficult to test and debug.

Peter Dimov replied:

> > That's exactly the problem std::error_code solves, as it's a (code,
> > domain) pair, so there's no need to translate.

Emil Dotchevski responded:

> That presumes that ENOENT represents the same _error_ when returned from
> two different functions. Generally, it does not. The correct strategy in
> C++ is to throw different types to indicate different errors, even when
> both end up carrying the same ENOENT.
> So it is critical to decouple the error code (std or otherwise) from _what_
> went wrong, and if you don't, you're butchering the ability to write
> error-neutral functions, which in practice means translating error codes
> from one domain to another, at every level, which is prone to errors.

Agree with your concern that an 'ENOENT' value may semantically mean
different things in different contexts (or not, depending on a specific
cross-domain mapping).

However, the 'std::error_code' implementation is intended to type-erase
those semantically-different meanings into the same object-type, but to
permit that "difference-checking" that would otherwise be performed with
different types, such as your example to throw two types to semantically
represent two different domains of errors.

class f1_domain : public std::error_category { ... };
class f2_domain : public std::error_category { ... };

std::error_code f1(...) { ...; return make_error_code(ENOENT,
get_f1_domain()); }
std::error_code f2(...) { ...; return make_error_code(ENOENT,
get_f2_domain()); }

  if(f1() == f2()) // ...can be true-or-false...

The "type-erasure" implementation within 'std::error_code' is provided by
the cross-domain mapping implemented in 'f1_domain' and/or 'f2_domain' (by
overriding virtual functions from 'std::error_category').

So, agree with your assertion that throwing different types will
disambiguate; but the 'std::error_code' attempts to similarly keep that
different-domain distinction, but through type-erasure (provided through

Boost list run by bdawes at, gregod at, cpdaniel at, john at