Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: Those boolean contexts are bugging me!

23 views
Skip to first unread message

Alain Ketterlin

unread,
Mar 18, 2016, 6:04:29 AM3/18/16
to
r...@zedat.fu-berlin.de (Stefan Ram) writes:

> int main()
> { double x; bool ok; do
> { if( ::std::cin >> x ) ...
>
> . It compiles fine.
[...]
> int main()
> { double x; bool ok; do
> { if( ok = ::std::cin >> x )...
>
> error: cannot convert
> 'std::basic_istream<char>::__istream_type {aka
> std::basic_istream<char>}' to 'bool' in assignment

"if ( bool ok = ... )" compiles fine.
"if ( ok = bool(...) )" compiles fine.

Before C++11 there was no operator bool() (it was operator void*())
Since C++11 it is "explicit operator bool()"

Regarding conditions for if statements, (N4296, 6.4§3) says:

"The value of a condition that is an initialized declaration in a
statement other than a switch statement is the value of the declared
variable contextually converted to bool (Clause 4). [...] The value of a
condition that is an expression is the value of the expression,
contextually converted to bool for statements other than switch [...]"

Then, (6.4§5) says: "If a condition can be syntactically resolved as
either an expression or the declaration of a block-scope name, it is
interpreted as a declaration."

So "if ( bool ok = cin>>x )" (an initialized declaration) and
"if ( cin>>x )" (an expression, interpreted as a declaration) are
treated the same, and both match the requirements of an explicit
constructor. (I would call the latter an "implicitly explicit
construction" :-)

In contrast, "if ( ok = cin>>x )" tries to do two things:
1) evaluate cin>>x (returning an istream&)
2) assign to a bool
The assignment fails, because it requires a conversion that is not
explicit. Making it explicit (ok = bool(cin>>x)) solves the problem, as
noted above. There is no need for an "if" statement to exhibit the
problem:

ok = cin>>x;

fails to compile as well.

My conclusion is that the explicit qualifier on "istream::operator bool()"
is the cause of the error.

Does that sound plausible? Thanks for the example.

-- Alain.

Alf P. Steinbach

unread,
Mar 18, 2016, 1:38:45 PM3/18/16
to
On 18.03.2016 05:04, Stefan Ram wrote:
> I have this program:
>
> #include <iostream>
> #include <ostream>
> #include <istream>
>
> int main()
> { double x; bool ok; do
> { if( ::std::cin >> x ) ...
>
> . It compiles fine. I used to believe that »::std::cin >> x«
> was being evaluated in some kind of »boolean context«.

It is, it is a /condition/.


> So I tried this slight modification, inserting »ok = «.
>
> #include <iostream>
> #include <ostream>
> #include <istream>
> #include <limits>
>
> int main()
> { double x; bool ok; do
> { if( ok = ::std::cin >> x )...

Now it's the complete assignment expression that is a /condition/.

The invocation of >> is not.


> But now I get this message:
>
> error: cannot convert
> 'std::basic_istream<char>::__istream_type {aka
> std::basic_istream<char>}' to 'bool' in assignment
>
> . Why can't he (gcc 5.1.1 -std=c++17) convert it (::std::cin
> >> x) to bool anymore?

Because from C++11 and onward the conversion is an `explicit` `operator
bool`, which [1]can only be invoked implicitly for a /condition/.

With C++03 it was however just an implicit conversion to `void*`, so
with C++03 the code should compile.

Maybe you can test that by using `-std=c++03`.

• • •

Silly thing: the choice expression in a `switch` is also a /condition/.


Cheers & hth.,

- Alf

Notes:
[1] Instead of using a cast or a bang-bang, I would write `not (cin >>
x).fail()`). It's more verbose but far more clear. Explicit = good. :)

0 new messages