
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.