Reputation: 871
When I use an std::istream object (in the example below from cplusplus.com, an std::ifstream) in a test : "if (myistreamobject)", the object, which is automatically allocated in the stack is never null, right ?... in the example below, we are using the same test to check if all the bytes were read from the file... and that's really a strange code, I usually use that style when I'm dealing with pointers...
I want to know which mechanism is used in std::istream to return a value in tests, and what that value really means... (the success/failure of the last operation ??) is it an overloading of a bool cast (like the const char* operator cast in the MFC class CString) or it is another technique ?
Because the object is never null, so putting it in a test will always return true.
// read a file into memory
#include <iostream> // std::cout
#include <fstream> // std::ifstream
int main () {
std::ifstream is ("test.txt", std::ifstream::binary);
if (is) {
// get length of file:
is.seekg (0, is.end);
int length = is.tellg();
is.seekg (0, is.beg);
char * buffer = new char [length];
std::cout << "Reading " << length << " characters... ";
// read data as a block:
is.read (buffer,length);
if (is) // <== this is really odd
std::cout << "all characters read successfully.";
else
std::cout << "error: only " << is.gcount() << " could be read";
is.close();
// ...buffer contains the entire file...
delete[] buffer;
}
return 0;
}
Upvotes: 1
Views: 3443
Reputation: 9735
The
operator bool()
returns true if the stream has no errors, false otherwise.
The "no error" concept is something related with the previous operation done on the stream itself.
For example: after you invoke the constructor
std::ifstream is ("test.txt", std::ifstream::binary);
A internal status flag in the stream object is set. So when you invoke the operator bool you check whether the construction operation fails or not.
Moreover the method
is.read(...)
also set this internal status flag, as you can see in the reference:
Errors are signaled by modifying the internal state flags: eofbit, failbit, badbit.
So after the method call, if the stream reaches the EOF (end-of-file) the state bit is set, and the operator bool will return a positive value.
That means in that case when you test the stream with
if (is) { ... }
and the status bit is set, then the condition will be verified and the if-branch will be taken.
Upvotes: 3
Reputation: 24269
if (expression)
tests it expression
evaluates to true
which is a boolean. It works for pointers because nullptr
/NULL
/0
evaluate to false
, and everything else true
. It works for integral values for the same reason.
For an object, it falls to operator bool()
, see http://en.cppreference.com/w/cpp/io/basic_ios/operator_bool.
Checks whether the stream has no errors.
1) Returns a null pointer if fail() returns true, otherwise returns a non-null pointer. This pointer is implicitly convertible to bool and may be used in boolean contexts.
2) Returns true if the stream has no errors and is ready for I/O operations. Specifically, returns !fail().
This operator makes it possible to use streams and functions that return references to streams as loop conditions, resulting in the idiomatic C++ input loops such as while(stream >> value) {...} or while(getline(stream, string)){...}.
Such loops execute the loop's body only if the input operation succeeded.
Upvotes: 4
Reputation: 2863
std::istream
has operator declared right this:
explicit operator bool() const;
When you write
if(SomeStdIstremObject) { ... }
really is calling if(SomeStdIstreamObject.operator bool())
not checking for non zero
Upvotes: 2