Boost logo

Boost :

Subject: [boost] PR: Remove safe_bool idiom from boost.tribool
From: Robert Ramey (ramey_at_[hidden])
Date: 2018-05-18 22:17:51


Removed usage of "safe_bool" idiom from tribool.

This was initially motivated by the fact that usage of this idiom with
all current and past gcc compilers with constexpr does not work. First
it reports reference to the address of a local member function as not
being constexpr. This may or may not be correct according to the
standard. FWIW clang is OK with it. Making the member function
constexpr fixes this error. But still there is a problem. in GCC, the
operator to implicitly covert the instance to a void * does not seem to
work. Invocation of this operator in the context of an argument to an
if(... or other conditional doesn't result in behavior similar to bool.
Not even a static cast to a bool seems to work. Again CLANG is OK with
all this. This has been reported as an issue to the GCC team.

One idea which has been tried is to use C++11 "explicit" as a substitute
from the safe_bool idiom. Unfortunately this breaks legacy code.

bool f(x) {
        return tribool(true); // fails
}

So this is not a great solution either.

Attempts to resolve this were inconclusive. This motivated me to think
about why the safe_bool idiom was being used here at all. According to
articles on safe_bool articles this main reason is to support the common
practice of using a not null value in a conditional:

Testable t;

if(t) ...

without accidentally permitting things like

if(t >> 1)...

The above would occur if Testable included an operator bool () const
member function.

Basically safe_bool is meant to support the common C/C++ practice of
implicity converting something to bool so we write something like if(t)
... to mean t "is_valid" or "is_not_null" or some such.

a) I don't think this idiom is a good idea and even more so in the
context of modern C++.

Conversion of a Testable instance to a bool instance should result in
something that looks/acts like a C bool - not something else like a void
* which C then maps to a bool. If we want to use a bool for something
like "is_valid" we'd be much better off just implementing is_valid
directly. There would be then no confusion, side effects or hand a waving.

b) it's an especially a bad idea for tribool.

The motivating concept behind tribool is that of some sort of "extended"
bool. The naming suggests that it acts like a bool. But since we've
used he safe_bool idiom, it doesn't any more. That is we can't use a
tribool anywhere a bool is used. So if we use operator bool we'll get a
tribool which acts like a bool - even when the original usage of bool
was a bad idea according to a) above. But at least we have the same
behavior for tribool and bool which is a lot more intuitive and less
confusing.

Also, changing to operator bool () will address the current problem with
GCC not supporting a constexpr version of tribool.

Accordingly, I've submitted this PR to change the implementation of
tribool to avoid the safe_bool idiom.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk