Boost logo

Boost :

Subject: Re: [boost] [outcome] Ternary logic -- need an example
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2017-05-19 13:42:29

> Ok, I remember, both error_code and exception_ptr are
> default-constructible. It is not immediately clear to me that a
> default-constructed error_code represents a no-error condition.

A null error code is widely held to mean "no error". Ditto with
exception_ptr. In any ASIO completion handler, you'll see:

void asio_handler(const error_code &ec, ...)

> In the blog
> post by Chris Kohlhoff you refer to, he uses the following enum for
> representing http error conditions:
> ```
> enum class http_error
> {
> continue_request = 100,
> switching_protocols = 101,
> ok = 200,
> ...
> gateway_timeout = 504,
> version_not_supported = 505
> };
> ```
> Which implies that numeric value 200 means no-error and a value initialized
> `http_error` is meaningless. Maybe this does not affect the value of a
> default-constructed `std::error_code`, but surely it adds to the confusion.

I have absolutely no idea why Chris chose "http_error" for that enum. It
should have been "http_status" because those are the HTTP status codes
as per

I am also highly unsure why you'd choose the error_code infrastructure
for these. It's not like almost all of the HTTP status codes (e.g. 306
Switch Proxy) can be any error condition except

Vinnie, what does Beast do?

>> Therefore calling o.error() on a valued outcome returning a default
>> constructed (null) error code is exactly correct: we return there is no
>> error.
> Only under some definition of "correct". By correct, you probably mean "not
> invoking UB" and "being compliant with your specification", but it is not
> intuitive at all that a function should return this or that when invoked in
> a context that is most likely a programmer's bug.

No, really a null error code meaning "no error here" is the widely held
interpretation. The reason I cannot categorically says it means no error
here is because the C++ standard guarantees that a null error code has
value 0 and the **system** category. And that's a defect, I think they
meant value 0 and the *generic* category, because if they had then the
standard would categorically guarantee a null error code means no error

As it currently stands, the standard accidentally has made a null error
code mean "system dependent behaviour" which if it didn't mean "no error
here" would fundamentally wreck the Networking TS and the Filesystem TS.

>> No undefined behaviour needed, and you can write your code using
>> Outcome with the hard assumption that o.error() will always return an
>> accurate view of the current state. No need to check .has_error(), or
>> anything like it.
> Modulo this situation with `http_error::ok == 200`. But with this you are
> also saying, the library provides two ways for checking if you have an
> error:
> o.has_error(); // option 1

This returns whether the outcome contains an error_code. Not whether
there is an error. A program might return an outcome containing a null
error_code. It probably is a bug, but Outcome can't reasonably enforce
how people misuse error_code, not least because of the C++ standard
defect above.

> o.error() == std::error_code{}; // option 2

Actually "!o.error()" but I think you meant to write that anyway.

This would be preferred over option 1. If the function returned an empty
outcome, this would throw, but that is probably a good thing.

> And by describing clear semantics for option 2, you are saying, it is
> equally fine to use option 2 for checking if we have an error. This
> encourages the usage of option 2, but I would not want my colleague
> programmers to start using this syntax, because I then cannot tell proper
> usages from inadvertent omissions. And reading the value of `error()`
> without having confirmed that some error occurred is almost surely a bug,
> even if you can assign a well defined semantics in `boost::outcome` for it.

Option 1 is misleading. Option 2 is correct, and means typing less
boilerplate e.g. if(o.error()) ... instead of if(o.has_error() &&
o.error()) ...

> I am fine with this scope disabled. However, `tribool` is still in scope,
> so I consider it valid to ask about its usefulness (especially given that
> all contexts in which it would prove useful is disabled). Maybe `tribool`
> should be also removed from the scope?

I believe you've convinced me to move tribool to under the advanced
operations macro. Thanks. Logged to


ned Productions Limited Consulting

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