Boost logo

Boost :

Subject: Re: [boost] PR: Remove safe_bool idiom from boost.tribool
From: Edward Diener (eldiener_at_[hidden])
Date: 2018-05-22 13:54:09


On 5/22/2018 1:23 AM, Robert Ramey via Boost wrote:
> On 5/21/18 7:05 PM, Gavin Lambert via Boost wrote:
>> On 22/05/2018 13:25, Robert Ramey wrote:
>
>>>> No, that's a perfect example of terrible code that should absolutely
>>>> generate a compiler error.  A narrowing conversion (from a source
>>>> type that can express more values than the destination type) should
>>>> absolutely *never* under any circumstances occur implicitly.
>>>
>>> I think that tribool is/was designed to promote this and in this case
>>> I find it useful and natural.
>>
>> 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.
>
>> Note that explicit bool is also designed to handle the case where used
>> in a conditional context in an implicit fashion, exactly the same as
>> safe_bool.
>
> Maybe, but it doesn't replicate the behavior of the current safe_bool.
> That is my point.
>
>> Explicit bool also avoids the unintended side effects of implicit bool
>> conversions, such as promotion to integer (as pointed out by Peter)
>> and unintended narrowing when returning or passing parameters.
>
> whatever the intention of safe_bool or explicit, they don't produce the
> same behavior.
>
>> Implicitly returning a tribool as a bool should be forbidden for
>> exactly the same reasons as returning an int64_t as an int32_t -- you
>> are losing information, and unless you have explicitly indicated that
>> this was intended (presumably because you know things that the
>> compiler does not), it should be assumed to be a bug, perhaps as a
>> result of a recent change of types or just an oversight.
>
> 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.  In this case there is a much better case for it than for
> optional.  Not that it matters. It's not a great idea to silently change
> the operation of a component which has been in usage for 15 years.  If
> this really bugs you, you can just make your own component - just call
> it trilliam, trit or something else.
>
>>> I don't think explicit was created to fix safe_bool.  In general I
>>> support usage of explicit.  But in this case I don't think it's a
>>> good match.
>>
>> The explicit keyword itself was not.  But "explicit operator bool"
>> itself was, as part of C++11.
>
> 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.
>
>> (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.
>
>> (Specifically, there's a loophole that allows implicit use of explicit
>> bool conversions when in a conditional context such as an if statement
>> where only a bool expression is valid.)
>
> 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.
>
>> 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.
>
>>> Right.  But then I'm imposing your view point on many users programs
>>> which already exist.  You're basically changing the intention of
>>> tribool.  You may well have a good argument that the very idea of
>>> tribool is a bad idea, that it should never have been made the way it
>>> was and that no one should use it, but that ship sailed long, long
>>> ago. It's not relevant here.
>>
>> No, you're the one trying to change the intent.
>>
>> Implicit bool conversions are a behavioural downgrade and will only
>> serve to introduce bugs.
>
> 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.
>
> I can't believe this is even an argument.
>
> LOL - neither can I.
>
> FWIW - my original suggestion was to conditionally specify "explicit"
> and eliminate the safe_bool from from the tribool component. This would
> solve my current problem and so I was happy when this PR was created.
>
> But then we discovered that other effects on current user code.  Also it
> became apparent that using explicit wasn't equivalent to the safe_bool
> idiom.  So making this change would silently change the semantics of a
> program depending on whether or not it was compiled with the switch
> std=c++11 or not.  I hope it's obvious that this would be a very bad
> idea.  So I considered all this and now I recommend we drop the
> safe_bool idiom and include an implicit conversion to bool for tribool.
> This wouldn't have this problem and makes things no worse than they are
> now.  To summarize there are for options:
>
> a) leave things as they are.  This includes a compile time error for
> constexpr gcc tribool code.  And also includes implicit conversion to a
> bool return value.
>
> 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.
>
> 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.
>
> d) Separately, there is the option to create a "more correct" version of
> tribool under a different name.
>
> in my view c) is the most practical option given the current situation.
> d) is an option for someone who has the time available and want's to
> create, document and submit to boost.  I personally don't have the time
> to do this.
>
> So, I would like the person responsible for maintaining tribool to
> accept this PR.

tribool is a CMT library.

>
> Robert Ramey


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