Using a reference in a conditional statement...

B

barcaroller

I was looking at some code that uses fstream:


#include <fstream>
//
// which includes:
// istream& getline( char* buffer, streamsize num );
//

ifstream fin;
while( fin.getline(line, size) ) {
...
}


If fin.getline() returns a reference, how could it be used in a conditional
statement? I've looked at the member functions and I could not find a
conversion to a bool type.
 
N

Neelesh Bodas

I was looking at some code that uses fstream:

    #include <fstream>
    //
    // which includes:
    // istream& getline( char* buffer, streamsize num );
    //

    ifstream fin;
    while( fin.getline(line, size) ) {
        ...
    }

If fin.getline() returns a reference, how could it be used in a conditional
statement?  I've looked at the member functions and I could not find a
conversion to a bool type.

class istream inherits operator void*().

  while( fin.getline(line, size) ) --> getline returns istream&,
which is converted to void pointer using operator void*(). The pointer
is then compared against (void*)0.

-Neelesh
 
B

barcaroller

class istream inherits operator void*().

while( fin.getline(line, size) ) --> getline returns istream&,
which is converted to void pointer using operator void*(). The pointer
is then compared against (void*)0.


Thank you but why would the C++ compiler convert the result to void* if
there's no pointer operation happening here. In a conditional statement
(if/while), shouldn't it attempt to convert to a bool and, if no such
conversion exists, fail.
 
N

Neelesh Bodas

Thank you but why would the C++ compiler convert the result to void* if
there's no pointer operation happening here.  In a conditional statement
(if/while), shouldn't it attempt to convert to a bool and, if no such
conversion exists, fail.

since fin.getline(line, size) occurs as a condition in 'while' loop,
the compiler sees if it (i.e. the object of type istream) can be
(somehow) (legally) converted to bool. The compiler sees that there is
operator void*() in class istream which can be used to convert a value
of type istream to a value of type void*. Then it can convert void* to
bool using "boolean conversion". Thus, an object of class istream can
be converted to an object of type bool using a user-defined conversion
followed by a standard-conversion. This is a valid conversion sequence
and this is the only sequence that can be used to convert an object of
type istream to an object of type bool in the current case - hence
there is no ambiguity. Therefore the compiler can safely choose this
option.

-Neelesh
 
J

Jerry Coffin

[email protected] says... said:
If fin.getline() returns a reference, how could it be used in a conditional
statement? I've looked at the member functions and I could not find a
conversion to a bool type.

The fact that it's a reference is irrelevant here -- what's being
evaluated is the object referred to by the reference. Rather than a
conversion to bool, what's being used here is the conversion to void *.
 
P

Paavo Helde

barcaroller said:
Thank you but why would the C++ compiler convert the result to void* if
there's no pointer operation happening here. In a conditional statement
(if/while), shouldn't it attempt to convert to a bool and, if no such
conversion exists, fail.

Because bool converts to int too easily and may cause mess elsewhere. See a
nice example in http://www.horstmann.com/cpp/pitfalls.html (search the
phrase: Why convert to void*? )

So it is a commonly accepted practice to define operator void*() in order
to emulate operator bool(). So there...

Paavo
 
D

Daniel Dearlove

barcaroller said:
Thank you but why would the C++ compiler convert the result to void* if
there's no pointer operation happening here. In a conditional statement
(if/while), shouldn't it attempt to convert to a bool and, if no such
conversion exists, fail.

This is a hangover from C where 0 represents false and anything else
represents true. The compiler does an implicit conversion to a more
general type to try and make sense of the sentence as it doesn't make
sense with a std::istream&. Thus, a std::istream& turns to a void*. This
is a NULL pointer when you reach the end of a stream and that, in turn,
represents false.

This implicit conversion is allowed because it inherits this behaviour
from one of it's parents. See:
http://www.cplusplus.com/reference/iostream/ifstream/ and click on the
"operator void*" link. Also, this is why they are generally considered A
Bad Thing (tm). i.e. unexpected behaviour.
 
J

James Kanze

Because bool converts to int too easily and may cause mess
elsewhere. See a nice example
inhttp://www.horstmann.com/cpp/pitfalls.html(search the
phrase: Why convert to void*? )

It's particularly dangerous in the case of the streams, since <<
and >> have overloads with int as the right operand. It's
somewhat less of a worry for classes which don't overload << and
So it is a commonly accepted practice to define operator
void*() in order to emulate operator bool(). So there...

Commonly accepted practice, in this case, varies. Some people
accept bool, as long as no operators are defined otherwise for
the class; others go even further, and return a pointer to a
privately declared type, or a pointer to member of a privately
declared type, in order to be even surer of no mis-use.

I tend to use the privately declared type myself, but if none of
the operators valid on int are defined for the class, I'd accept
any of the solutions, including bool, in design review. And I
recognize special cases---stream-like classes (e.g.
[io]xdrstream) will use void* (because they derive from
std::basic_ios, but also because it's what is expected of a
stream), smart pointers almost must use the private class (or
pointer to member to private class), because you want it anyway
to support comparison with NULL, etc.
 

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

No members online now.

Forum statistics

Threads
473,733
Messages
2,569,440
Members
44,832
Latest member
GlennSmall

Latest Threads

Top