void * instead of bool

M

Marcin Kalicinski

Hi,

Why is there void* conversion to check for std::istream failure bit? Why not
a conversion to bool?

When I try to return an istream from a function that actually returns bool,
I get the following warning (in VC .NET):

warning C4800: 'void *' : forcing value to bool 'true' or 'false'
(performance warning)

I can get rid of it by returning (stream != 0) or (!!stream), but it looks
ugly to me. Besides that, I suspect that it might perhaps be generating
unoptimal code. Compiler does not know that void* value holds only 0 or 1 in
the case of streams, and adds extra code to prevent the value going out of
bool range. At least that's what the warning is trying to say.

Is there any reason to avoid automatic conversion to bool and prever
conversion to void* instead?

Marcin
 
K

Karl Heinz Buchegger

Marcin said:
Hi,

Why is there void* conversion to check for std::istream failure bit? Why not
a conversion to bool?

Because you definitily don't want this to compile:

ifstream if;
int j;

j = 2 + if;
When I try to return an istream from a function that actually returns bool,
I get the following warning (in VC .NET):

warning C4800: 'void *' : forcing value to bool 'true' or 'false'
(performance warning)

I can get rid of it by returning (stream != 0) or (!!stream), but it looks
ugly to me.

YOu can turn off that warning completely in VC++ with the help of a pragma
Besides that, I suspect that it might perhaps be generating
unoptimal code.

Don't worry about that. You will never notice the difference.
Your PC can do around 1 * 10^9 operations per second and you
worry about 1 or 2 instructions more or less.
Compiler does not know that void* value holds only 0 or 1 in
the case of streams, and adds extra code to prevent the value going out of
bool range. At least that's what the warning is trying to say.

It is.
But in practice this isn't a problem at all.
Is there any reason to avoid automatic conversion to bool and prever
conversion to void* instead?

See above.
 
J

John Harrison

Marcin Kalicinski said:
Hi,

Why is there void* conversion to check for std::istream failure bit? Why not
a conversion to bool?

If you have a conversion to bool then the following nonsense would compile

float f = cin;

Conversion to void* is less likely to be called accidentally.
When I try to return an istream from a function that actually returns bool,
I get the following warning (in VC .NET):

warning C4800: 'void *' : forcing value to bool 'true' or 'false'
(performance warning)

I can get rid of it by returning (stream != 0) or (!!stream), but it looks
ugly to me. Besides that, I suspect that it might perhaps be generating
unoptimal code. Compiler does not know that void* value holds only 0 or 1 in
the case of streams, and adds extra code to prevent the value going out of
bool range. At least that's what the warning is trying to say.

You could do this

return some_stream.good();
Is there any reason to avoid automatic conversion to bool and prever
conversion to void* instead?

See above.

john
 
M

Marcin Kalicinski

Besides that, I suspect that it might perhaps be generating
Don't worry about that. You will never notice the difference.
Your PC can do around 1 * 10^9 operations per second and you
worry about 1 or 2 instructions more or less.

I always thought that C++ main advantage over other languages is that almost
optimal code can be generated from it.

Not the case here, but 2 extra instructions make difference sometimes, no
matter how fast will CPUs become, as there will always be problems where
they are still too slow.

Fortunately, John has already pointed out that stream.good() will do
optimally without warning and those extra 2 instructions, so C++ is saved
:)

Marcin
 
A

Andrew Koenig

Because you definitily don't want this to compile:

ifstream if;
int j;

j = 2 + if;

Even more entertaining:

int j = 42;
std::cout >> j; // Oops, I really should have written <<
 
A

Alf P. Steinbach

* Karl Heinz Buchegger:
Because you definitily don't want this to compile:

ifstream if;
int j;

j = 2 + if;

Assuming you meant to use a non-keyword instead of "if", _why_ on or off
Earth would I definitily (?) not want that to compile?

The same goes for Andrew's example.

On the contrary, a good design does not needlessly limit the user to
do only things the designer is able to foresee the usefulness of.

I think there are two more realistic explanations.

One is that perhaps the original design dates from a time before 'bool'
was introduced in the language. Another is that perhaps there is some
subtle issue with e.g. function overload resolution, e.g. passing an
ifstream object to a constructor where one overload takes a bool. In
the latter case (which does not exclude the first) the conversion to
void* is already one conversion, and void* is a very unspecific type, so
a direct conversion to a more sensible type would, ideally, be chosen.
 
R

Rolf Magnus

John said:
If you have a conversion to bool then the following nonsense would
compile

float f = cin;

Why should one worry about that? There is a lot of nonsense that does
compile, but isn't a problem, because nobody writes that nonsense
anyway.
 
A

Andrew Koenig

Assuming you meant to use a non-keyword instead of "if", _why_ on or off
Earth would I definitily (?) not want that to compile?

The same goes for Andrew's example.

which was:

int j;
cout >> j; // Oops, I meant to write <<
I think there are two more realistic explanations.

One is that perhaps the original design dates from a time before 'bool'
was introduced in the language. Another is that perhaps there is some
subtle issue with e.g. function overload resolution, e.g. passing an
ifstream object to a constructor where one overload takes a bool.

Actually, my example is the original motivating reason for having the stream
classes convert to void * rather than to bool. Well, not quite, because the
example long predates the existence of bool--but exactly the same problem
came up when we considered having the iostream classes converting to int.
 
A

Alf P. Steinbach

* Andrew Koenig:
which was:

int j;
cout >> j; // Oops, I meant to write <<


Actually, my example is the original motivating reason for having the stream
classes convert to void * rather than to bool. Well, not quite, because the
example long predates the existence of bool--but exactly the same problem
came up when we considered having the iostream classes converting to int.

It seems then that you (all) did something that perhaps was right, for
the wrong reasons... ;-)

Can you recall why implicit conversion was judged to be desirable when
there clearly were issues with that that were regarded as "problems"?
 
R

Rob Williscroft

Alf P. Steinbach wrote in in
comp.lang.c++:
Assuming you meant to use a non-keyword instead of "if", _why_ on or off
Earth would I definitily (?) not want that to compile?

Perhaps because:

j = 2 + bool( if );

is fine ('if' aside).
The same goes for Andrew's example.

here it is:

<quote>
int j = 42;
std::cout >> j; // Oops, I really should have written <<
</quote>

bool -> int is 1 or 0, 1 >> non-zero is 0 (or undefined (42 an on a
32 bit system for eg)).

int i = std::cout && !j;

If you must :).
On the contrary, a good design does not needlessly limit the user to
do only things the designer is able to foresee the usefulness of.

But an "input stream" is not a number.

Also there is no limit, fail() is perfectly accessible.
I think there are two more realistic explanations.

One is that perhaps the original design dates from a time before 'bool'
was introduced in the language.

Not convincing, int does equally well.
Another is that perhaps there is some
subtle issue with e.g. function overload resolution, e.g. passing an
ifstream object to a constructor where one overload takes a bool. In
the latter case (which does not exclude the first) the conversion to
void* is already one conversion, and void* is a very unspecific type, so
a direct conversion to a more sensible type would, ideally, be chosen.

The original design (AFAICT) called for:

if ( std::cin >> a ) /* whatever */;

and also:

std::cin >> a >> b;

to be valid (and meaningfull).

The first suggests operator >> should return bool, the second
then suggests std::istream should have a conversion to bool.

But operator bool means that a stream is also a number
which (IM<earth bound>O) is *not* desirable.

Rob.
 
A

Alf P. Steinbach

* Rob Williscroft:
Alf P. Steinbach wrote in in
comp.lang.c++:


Perhaps because:

j = 2 + bool( if );

is fine ('if' aside).

C++ is full of alternative ways of achieving anything, some more
explicit than others. We do not wish the implicit ones to not compile
merely because there is some explicit way of achieving the same. On the
contrary, programmers would be less than enthusiastic about henceforth
having to write a = a + 1, with compile errors on a += 1 and ++a (say).

Hence the argument does not hold.

Having an explicit way is not a reason to ban the implicit ways.

here it is:

<quote>
int j = 42;
std::cout >> j; // Oops, I really should have written <<
</quote>

bool -> int is 1 or 0, 1 >> non-zero is 0 (or undefined (42 an on a
32 bit system for eg)).

In other words, you can see no advantage.

Neither can I, but it's harmless.

int i = std::cout && !j;
If you must :).

Already discussed above.


But an "input stream" is not a number.

But an "input stream" is not a bool.

But an "input stream" is not a void*.

If you mean this should not have been an implicit operation, I agree.

Also there is no limit, fail() is perfectly accessible.


Not convincing, int does equally well.

One reason 'bool' was introduced was that int does not do equally well;
in particular int is not distinct from int.

The original design (AFAICT) called for:

if ( std::cin >> a ) /* whatever */;

and also:

std::cin >> a >> b;

to be valid (and meaningfull).

The first is a requirement to support side-effect based code, which is
ungood square (TM). The second, operator chaining, isn't so bad on its
own, but it precludes better designs so it's also a bit ungood (TM). I
rather liked the original printf-like formatting that Bjarne suggested,
and which I believe is now carried further, to type safety, in Boost.

The first suggests operator >> should return bool, the second
then suggests std::istream should have a conversion to bool.

Yes, and all that to support two ungood requirements, and void* as a
replacement to a-void accidental invocation of the shift operator, which
would be detected in the first rough trying-out of the program anyway.

But operator bool means that a stream is also a number
which (IM<earth bound>O) is *not* desirable.

And following that logic: an "input stream" is not a void*.
 
A

Andrew Koenig

Can you recall why implicit conversion was judged to be desirable when
there clearly were issues with that that were regarded as "problems"?

Because we didn't want to break C compatibility.
 
A

Alf P. Steinbach

* Andrew Koenig:
Because we didn't want to break C compatibility.

Does that mean that implicit conversion was required to support the
coding convention established in C (namely a side-effect based loop
condition), or that implicit conversion war required to upheld direct C
_language_ compatibility (I don't see what could be broken by not having
an implicit conversion)?
 
A

Andrew Koenig

Does that mean that implicit conversion was required to support the
coding convention established in C (namely a side-effect based loop
condition), or that implicit conversion war required to upheld direct C
_language_ compatibility (I don't see what could be broken by not having
an implicit conversion)?

It means that the rules for converting built-in types were intentially the
same for C++ as they were for C.

Maybe I'm not understanding what you mean when you say "implicit conversion
was judged to be desirable." What conversion are you speaking about,
specifically?
 
A

Alf P. Steinbach

* Andrew Koenig:
It means that the rules for converting built-in types were intentially the
same for C++ as they were for C.

Maybe I'm not understanding what you mean when you say "implicit conversion
was judged to be desirable." What conversion are you speaking about,
specifically?

Having the implicit conversion to void*, operator void*(), as opposed to

not having it which would require explicit use of e.g. fail() (better)
and would avoid the "problem" with accidental shift-operator invocation.
 
A

Andrew Koenig

Alf P. Steinbach said:
* Andrew Koenig:
not having it which would require explicit use of e.g. fail() (better)
and would avoid the "problem" with accidental shift-operator invocation.

There was a general desire to be able to write code like

while (cin >> x)
do_something_with(x);

instead of

while (cin >> x, !x.eof())
do_something_with(x);

That kind of notational compactness is important in a heavily used library.
 
A

Alf P. Steinbach

* Andrew Koenig:
There was a general desire to be able to write code like

while (cin >> x)
do_something_with(x);

instead of

while (cin >> x, !x.eof())
do_something_with(x);

That kind of notational compactness is important in a heavily used library.

Uhm, yes, that's what I thought.

Topic drift: what about

namespace std
{
inline bool failed( std::istream const& s ){ return s.fail(); }
}

...

while( !failed( cin >> x ) )
{
doSomethingWith( x );
}

I think that's a much better way to provide convenience operations than
a type conversion operator -- also gives readable & explicit code...
 
P

Prateek R Karandikar

Hi,
Why is there void* conversion to check for std::istream failure bit? Why not
a conversion to bool?

Simple answer: because the Standard says so.
When I try to return an istream from a function that actually returns bool,
I get the following warning (in VC .NET):

warning C4800: 'void *' : forcing value to bool 'true' or 'false'
(performance warning)

I can get rid of it by returning (stream != 0) or (!!stream), but it looks
ugly to me. Besides that, I suspect that it might perhaps be generating
unoptimal code. Compiler does not know that void* value holds only 0 or 1 in
the case of streams, and adds extra code to prevent the value going out of
bool range. At least that's what the warning is trying to say.

Is there any reason to avoid automatic conversion to bool and prever
conversion to void* instead?

As I said before, the reason is because the Standard says so.

If you are curious about knowing *why* the Standard says what it says,
ask in comp.std.c++.

-- --
To iterate is human, to recurse divine.
-L. Peter Deutsch
-- --
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top