Boost logo

Boost :

Subject: Re: [boost] PR: Remove safe_bool idiom from boost.tribool
From: Gavin Lambert (gavinl_at_[hidden])
Date: 2018-05-22 06:17:54


On 22/05/2018 17:23, Robert Ramey wrote:
> On 5/21/18 7:05 PM, Gavin Lambert wrote:
>> No, it wasn't.  The somewhat-implicit bool conversion (safe_bool) was
>> expressly for use within if statements, as demonstrated in the
>> documentation
>> (https://www.boost.org/doc/libs/1_67_0/doc/html/tribool/tutorial.html). Nowhere
>> in this documentation will you find implicitly returning a tribool as
>> a bool.
>
> I doesn't have to since void * (safe_bool) can be converted implicitly
> as bool. And there are many, many cases where this is done.  You might
> not think this is a great idea, but it's a fact.  These programs will
> fail to compile if you change safe_bool to explicit.

The intended purpose of safe_bool implicitly converting to bool was for
use in conditional expression contexts.

That it permitted other narrowing conversions is not intended and is
unfortunate.

> Now you're re-hashing the design of tri-bool.  It works the way it has
> for many, many years.  Its consistent with other components such as
> std::optional which do the same thing and what many people are happy
> with.

std::optional was added after C++11 and as such uses explicit bool. It
does not have implicit conversions.

Older versions of boost::optional did use safe_bool, but have since been
updated to use explicit bool where compiler-supported (via macro
BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT).

So both of these support my argument, not yours.

(Perhaps the better PR would be to make tribool use that macro, defined
in boost/core/explicit_operator_bool.hpp)

> actually "explicit" can be applied to conversion operators of all types
> - intrinsic as well as user defined.  I'm sure there was no intent to
> think in terms of "explicit bool" as some special situation.

I'm referring to the contextual bool conversion mentioned later on. It
is indeed a special situation.

>> (You can use the same keywords pre-C++11 but it will not have the
>> correct effect.)
>
> Hmmm - I was not  aware that "explicit" could be applied to conversion
> operators before C++11.

True, I misspoke; I was thinking of explicit constructors, which don't
apply here as it's the wrong conversion direction.

> LOL - Right.  That's the root of the whole discussion.  At some point
> long ago everyone thought these implicit conversions were a good idea.
> I presume they still do as we have optional which include implicit
> conversions to bool and I'm sure there are some more.

Implicit widening conversions can still be a good idea. Implicit
narrowing conversions never are. And again optional does not do what
you claim.

>> Thus "explicit" by itself disables all the unintended implicit usages
>> of the conversion, and C++11 then enables the one intended implicit use.
>
> Hmmm - I thought that C++11 enables implicit conversion of any integer
> or pointer to a bool for purposes of if, when etc.

Anything that is explicitly convertible to bool, yes. That doesn't
invalidate my point.

> maybe for components like optional, but I don't see it happening for
> tribool. continuing to permit tribool implicitly convert to bool - as it
> currently - won't introduce any more bugs than it does currently - if
> there are any.

This is incorrect, as Peter already pointed out.

Additionally, you should consider the effect on future code -- it's not
really a great argument to claim that a safety railing is no longer
necessary because nobody has fallen off the cliff while the safety
railing was there.

> b) move to explicit when supported. - which eliminates the compile error
> but makes behavior dependent to the C++ standard used to compile.  It
> will also break a lot of current user code.

This is the only option that makes sense to me. If that breaks user
code, it is a net positive effect because that code was already broken
-- and it is trivial to correct it where actually intended.

This is no different than when boost::optional switched to explicit
bool, to use your own example correctly.

> c) implement inplicit conversion to bool.  This breaks no current code
> and resolves the current constexpr issue.  It does permit t + u where t
> and u are results of bool conversions.  This will be fixed automatically
> for C++17.

As far as I am aware, this is not correct; bool is still implicitly
convertible to int in all versions of C++.
(And https://en.cppreference.com/w/cpp/language/implicit_conversion agrees.)

I welcome proof otherwise; although that still would not change my
opinion as it doesn't help those using pre-C++17 compilers.


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