Boost logo

Boost :

Subject: Re: [boost] PR: Remove safe_bool idiom from boost.tribool
From: Robert Ramey (ramey_at_[hidden])
Date: 2018-05-19 16:09:54


On 5/19/18 8:18 AM, Andrey Semashev via Boost wrote:
> On Sat, May 19, 2018 at 1:17 AM, Robert Ramey via Boost
> <boost_at_[hidden]> wrote:
>>
>> 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.
>
> C++11 explicit conversion operators don't support this use case, so if
> it works with the safe_bool idiom then it is either a bug or an
> unavoidable unfortunate limitation of the emulation.

I don't think that one can conclude that because C++11 expicit
conversion operators don't support a use case that it's a bug. The
question is whether conversion to bool from tribool makes some sort of
sense. I think it does - regardless of what C++11 actually does.

> User's code should be updated in this case.

This code has been in usage for 15 years. One can just start using the
explicit bool conversion and then break tons of code - some of it very
old. In one case (QT) this change generated 100's of syntax errors in
existing code.
>> 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.

> There are also other accidents that are intended to be prevented by
> safe_bool/explicit conversion operators. For example:
>
> void foo(bool f);
>
> foo(t);

Right - I get this. I think this is a good conversion to support. That
is why my change supports implicit conversion from tribool to bool.

> Some accidents are also prevented by the recent changes to the
> language. For example, increment/decrement operations on bool are
> deprecated since C++11 and removed since C++17.

Hmmm - I did not know that. Since one of the main motivations of
safe_bool is to inhibit this behavior, and it will shortly be inhibited
by a C++17 in any case, it supports my argument for eliminating
safe_bool idiom from tribool. Thanks for noticing this.

>> 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.
>
> This is obviously very case-specific, but I find certain types like
> smart pointers or optional rather natural to support explicit
> conversion to bool. Such an operation has obvious meaning where the
> conversion would apply. Having empty() or is_null() instead would just
> increase verbosity for no gain.

> Note that having a dedicated method is also useful in other contexts.
> Like in my foo example above, when you actually want to call that
> function with a bool that indicates whether Testable is valid or some
> such.

Actually, all these cases are "case specific". I have views on the
conversion to bool for optional an others, but we're only talking about
tribool here.

>> 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.

and implement a normal operator bool instead!

> I would say I agree that the conversion operator is not a good idea
> with regard to tribool.

Hmmm - I'm proposing adding and ordinary conversion operator to convert
tribool to bool. How can you agree with me while saying it's not a good
idea?

> But I don't quite understand how making the
> conversion _easier_ to invoke would make it better. If anything, I
> would rather work towards removing the conversion operator entirely
> instead of making it implicit. I think this change is a step in the
> wrong direction.

Sure we can disagree. I've made my argument - I think it's pretty clear.

Robert Ramey


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