Stream state question

J

john

In TC++PL 3, on page 616, "class basic_ios" has the public members

"operator void *() const; // nonzero if !fail()
bool operator!() const { return fail(); }"

for using them in conditional statements in the style:

if(cin) // if( !void *(0) )

if(!cin) // if( cin.operator!()


Why isn't operator bool() used instead? For historical reasons?
 
A

Alf P. Steinbach

* john:
In TC++PL 3, on page 616, "class basic_ios" has the public members

"operator void *() const; // nonzero if !fail()
bool operator!() const { return fail(); }"

for using them in conditional statements in the style:

if(cin) // if( !void *(0) )

if(!cin) // if( cin.operator!()


Why isn't operator bool() used instead? For historical reasons?

The implicit conversion with operator bool() would allow things like
passing a stream object to int formal function argument.

The implicit conversion with void* is more narrow in what it can match.

However, the worst problem with implicit conversions is that they are
not explicit -- you can't see them from reading the program text.

So one relevant question is, why is there an implicit conversion at all?

And for that, I have no other answer than that iostreams are not in
general examples of best practice as regards design: they just evolved
from some practical small early classes, into impractical huge beasts.


Cheers, & hth.,

- Alf
 
J

James Kanze

In TC++PL 3, on page 616, "class basic_ios" has the public members
"operator void *() const; // nonzero if !fail()
bool operator!() const { return fail(); }"
for using them in conditional statements in the style:
if(cin) // if( !void *(0) )
if(!cin) // if( cin.operator!()
Why isn't operator bool() used instead? For historical
reasons?

The most obvious reason is that iostream was part of the
language before bool was. And that bool is an integral type,
which can lead to unexpected results when used with the >> and
<< operators.
 
J

john

James said:
The most obvious reason is that iostream was part of the
language before bool was. And that bool is an integral type,
which can lead to unexpected results when used with the >> and
<< operators.


basic_osstream has explicit "operator<<()" definitions for both "bool"
and "const void *".
 
J

James Kanze

James Kanze wrote:
basic_osstream has explicit "operator<<()" definitions for both "bool"
and "const void *".

Not with those types on the right hand side. The problem is
that given something like "std::cout << myType", where myType
converts implicitly to an integral type, if the implicit
conversion were to bool (and not void*) the compiler will find a
match even if the user has forgotten to declare the desired <<
operator. This is not true for void*.

Note that void* doesn't solve everything, either. For example,
if you write something like "std::cout << std::cin", meaning to
write "std::cout << std::cin.rdbuf()", the compiler still finds
a match. In order to avoid such issues, some people have
suggested the use of a pointer to member of a private class.
(Since no user supplied function can use the private class, no
user defined function can be declared to take it.)

In practice, at least the way I write code, a conversion to bool
would not cause problems. But the current situation works well
too, and I certainly don't see any need to change it.
 
A

Alf P. Steinbach

* James Kanze:
Not with those types on the right hand side. The problem is
that given something like "std::cout << myType", where myType
converts implicitly to an integral type, if the implicit
conversion were to bool (and not void*) the compiler will find a
match even if the user has forgotten to declare the desired <<
operator. This is not true for void*.

#include <iostream>
#include <ostream>

int main()
{
using namespace std;
cout << cout << std::endl;
}


Cheers,

- Alf
 
A

Alf P. Steinbach

* Alf P. Steinbach:
* James Kanze:

#include <iostream>
#include <ostream>

int main()
{
using namespace std;
cout << cout << std::endl;
}

Oh, sorry, now I see you mention that case later.

But that means that I fail to understand what you mean above.

E.g.

#include <iostream>
#include <ostream>

struct S{ operator void*() const { return 0; } };

int main()
{
using namespace std;
cout << S() << std::endl;
}

must compile fine with any standard-conforming compiler.


Cheers,

- Alf
 

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,794
Messages
2,569,641
Members
45,353
Latest member
RogerDoger

Latest Threads

Top