Interest in removing implicit conversions to bool for fundamental types?

67 views
Skip to first unread message

Xeo

unread,
Aug 27, 2013, 8:05:32 AM8/27/13
to std-pr...@isocpp.org
Conversions to bool are generally a good thing: they're like a uniform interface for checking the "validity" of an object, if the "validity" is unambiguous - like for pointers. However, as could be see with the invention of the "safe-bool idiom", *implicit* conversions to bool can cause many problems and aren't very favorable. C++11 added explicit conversion operators and so-called *contextual conversions to bool*, which is a definite improvement - but the built-in types still suffer from implicit conversions.

On a slight tangent: Something that has formed in the back of my head in the last few days was an unary postfix `operator?`, which explicitly asks for a contextual conversion to bool. It's basically the conditional operator without the branches.
The idea originally came up when somebody wanted to provide a function which checks the validity of his object by inspecting the underlying `std::optional`-like object which provides an `explicit operator bool`, but not an `engaged()` or `initialized()` or similar function.
That could be seen as an interface-fail, but one has to live with it.

class foo{
  std
::optional<T> _impl;
// ...
 
bool test() const{ return _impl; }
};

This obviously won't compile, as the conversion to bool would be considered *implicit* here. We then discussed several "workarounds":

return bool(_impl); // very subjective feeling: meeeeeeeh
return static_cast<bool>(_impl); // unwieldy
return _impl ? true : false; // feels redundant
return _impl && true; // feels redundant and obscure
return !!_impl; // double-banging in C++? oh come on

In comes `operator?`

return _impl?; // concise and (imo) clear

So, returning from that tangent, said `operator?` would then also be used with the fundamental types, providing a clear migration path for code that relies on the implicit conversion to bool.

There's no proposal at this point, as I just want to collect general interest and feedback.

Regards

Maurice Bos

unread,
Aug 27, 2013, 8:22:53 AM8/27/13
to std-pr...@isocpp.org
I'm actually surprised that the conversion is *not* considered explicit in both:
    [1] bool test() { return some_optional; }
and
    [2] bool foobar = some_optional;

In both cases it's very clear a conversion to bool is desired. 'bool' is even explicitly written, unlike in
    [3] if (some_optional);
in which it is considered 'explicit', even though to me it seems at most as explicit than the first two examples I gave.

I thought explicit operator bool was only to prevent
    [4] int baz = some_optional;
but I don't see why it would be handy prevent [1] and [2], which seems pretty explicit.

The good old 'safe bool idiom' does allow [1], [2] and [3], but not [4], which is usually (always?) what I want. (In contrast to the explicit operator bool, which only allows [3].)



2013/8/27 Xeo <hivem...@hotmail.de>

--
 
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

Jonathan Wakely

unread,
Aug 27, 2013, 8:55:22 AM8/27/13
to std-pr...@isocpp.org


On Tuesday, August 27, 2013 1:22:53 PM UTC+1, Maurice Bos wrote:
I'm actually surprised that the conversion is *not* considered explicit in both:
    [1] bool test() { return some_optional; }
and
    [2] bool foobar = some_optional;

Are you also surprised that a type with an explicit constructor can't be used in the same way?

std::unique_ptr<int> ptr() { return new int; }

std::unique_ptr<int> ptr = new int;

Personally I'd like [1] to be considered "explicit" for both constructors and conversions operators, but until then it's better that the rules are consistent.

David Krauss

unread,
Aug 27, 2013, 9:40:12 AM8/27/13
to std-pr...@isocpp.org


On Tuesday, August 27, 2013 8:05:32 PM UTC+8, Xeo wrote:
Conversions to bool are generally a good thing: they're like a uniform interface for checking the "validity" of an object, if the "validity" is unambiguous - like for pointers. However, as could be see with the invention of the "safe-bool idiom", *implicit* conversions to bool can cause many problems and aren't very favorable. C++11 added explicit conversion operators and so-called *contextual conversions to bool*, which is a definite improvement - but the built-in types still suffer from implicit conversions.

On a slight tangent: Something that has formed in the back of my head in the last few days was an unary postfix `operator?`, which explicitly asks for a contextual conversion to bool. It's basically the conditional operator without the branches.
 
Unary postfix "?" used as the condition to ternary "?" would invite the "??" sequence which introduces a trigraph. That's just a unary "!" away from disaster.


There's no proposal at this point, as I just want to collect general interest and feedback.

It sounds like you proposed a postfix "?" operator. The benefits seem very dubious.

Xeo

unread,
Aug 27, 2013, 9:51:40 AM8/27/13
to std-pr...@isocpp.org
On Tuesday, August 27, 2013 3:40:12 PM UTC+2, David Krauss wrote
 
Unary postfix "?" used as the condition to ternary "?" would invite the "??" sequence which introduces a trigraph. That's just a unary "!" away from disaster.

Although I see the problem, since the conditional operator already invokes a contextual conversion to bool, you don't need postfix-? here. Also, even in the event that you end up with a trigraphed `|`, it will yield a hard-error, albeit not a very intuitive one I admit.
 

There's no proposal at this point, as I just want to collect general interest and feedback.

It sounds like you proposed a postfix "?" operator. The benefits seem very dubious.

The proposal is actually a combination of what is in the topic of the thread and the postfix-`operator?`, since just the former would provide no clear migration path.
Reply all
Reply to author
Forward
0 new messages