if (cin >> x) - Why can you use that condition?
C++VariablesIf StatementCinC++ Problem Overview
I have been using "Accelerated C++" to learn C++ over the summer, and there's a concept which I don't seem to understand properly.
Why is
int x;
if (cin >> x){}
equivalent to
cin >> x;
if (cin){}
By looking at the code, it seems to me that we're using cin as a variable. But, I thought it was a function. Why can we use cin in this way when it is x that has whatever value we input into our keyboard?
C++ Solutions
Solution 1 - C++
cin
is an object of class istream
that represents the standard input stream. It corresponds to the cstdio
stream stdin
. The operator >>
overload for streams return a reference to the same stream. The stream itself can be evaluated in a boolean condition to true or false through a conversion operator.
cin
provides formatted stream extraction. The operation
cin >> x;
where "x" is an int will fail if a non-numeric value is entered. So:
if(cin>>x)
will return false
if you enter a letter rather than a digit.
This website on tips and tricks using C++ I/O will help you too.
Solution 2 - C++
Note: Answer updated four years after the fact to address both C++98/03 and C++11 (and beyond).
std::cin
is an instance of a std::istream
. That class provides two overloads that pertain to this question.
operator >>
reads data from the stream into the target variable if that is possible. If the immediate contents of the stream cannot be translated into the type of the target variable, the stream is instead marked as invalid and the target variable is left untouched. Regardless of the success/failure of the operation, the return value is a reference to the stream.- Either
operator void*()
(pre-C++11), which converts the stream reference to avoid*
pointer, orexplicit operator bool()
(C++11), which converts the stream reference to a boolean. The result of this conversion is a non-null pointer (pre-C++11) ortrue
(C++11) if the stream is valid, but the null pointer (pre-C++11) orfalse
(C++11) if the stream isn't valid.
An if
statement needs either a boolean, an integer, or a pointer as the quantity to be tested. The result of std::cin >> x
is a reference to an istream
, which is none of the above. However, the class istream
does have those conversion operators which can be used to transform the istream
reference to something usable in an if
statement. It is the version-specific conversion operator that the language uses for the if
test. Since failure to read marks the stream as invalid, the if
test will fail if the read didn't work.
The reason for the more convoluted operator void*
conversion member prior to C++11 is that it wasn't until C++11 that the already existing explicit
keyword was extended to apply to conversion operators as well as constructors. A non-explicit operator bool()
would have presented far too many opportunities for programmers to shoot themselves in the foot. There are problems with operator void*()
as well. The "safe bool idiom" would have been a fix, but simply extending explicit
accomplished exactly what the safe bool idiom accomplishes, and without having to use a lot of SFINAE magic.
Solution 3 - C++
cin
is a (global) variable of type istream
, not a function.
The istream
class overrides the >>
operator to perform input and return a reference to the object you called it on (cin
).
Solution 4 - C++
cin
is variable in std
namespace.
operator>>
return reference to cin
, because of it you can write: cin >> a >> b
, instead of cin >> a; cin >> b;
Solution 5 - C++
The answers above are informative. Here I just give an extra comment.
std::cin
is an object of class istream
and represents the standard input stream (i.e. the keyboard) which corresponds to stdin
in C stream.
cin >> x
would firstly read an int from the standard input stream and assignment it to x
. After that return a self reference to cin
. So the return value of function call cin >> x
is still cin
.
So from the point of if condition, if(cin)
and if(cin >> x)
resemble each other. The standard IO Library defines a function for the stream like this (depends on implementation):
explicit operator bool() const; // C++11
or
operator void*() const; //C++98, C++2003
From this two declarations, we know they cast the stream type directly or indirectly(through void*
pinter to bool
which is obvious) to bool
type.
Within this two functions, they depends on some basic IO steam statuses(class fields) to determine whether return false or true (for void*
case, it is nullptr
or not).
cin
is an instance of class istream
which inherits the casting-to-bool function. So it works!
Solution 6 - C++
because the result of the expression
cin >> x
evaluates to
cin
after the stream is read.
Solution 7 - C++
std::cin
is an instance of the std::istream
class.
cin >> x
is just calling a function on the cin
object. You can call the function directly:
cin.operator >>(x);
To allow you to read multiple variables at once the operator >>
function returns a reference to the stream it was called on. You can call:
cin >> x >> y;
or equivalently:
cin.operator >>(x).operator >>(y);
or:
std::istream& stream = cin.operator >>(x);
stream.operator >>(y);
The final part of the puzzle is that std::istream
is convertible to bool
. The bool is
equivalent to calling !fail()
.
So in the following code:
int x;
std::istream& stream = std::cin.operator >>(x);
bool readOK = !stream.fail();
if (readOK)
{
std::cout << x << "\n";
}
bool readOK = !stream.fail();
can be reduced to just bool readOK = stream;
.
You don't need a separate bool
to store the stream state so can just do if (stream)
.
Removing the temporary stream
variable gives if (std::cin.operator >>(x))
.
Using the operator directly gets us back to the original code:
int x;
if (std::cin >> x)
{
std::cout << x << "\n";
}
Solution 8 - C++
-
cin
is an instance ofistream
, see http://www.cplusplus.com/reference/iostream/cin/. -
the
>>
operator ofistream
will return its left operand, in this case it iscin
, see http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/. This operator will setfailbit
on if no characters were extracted from thecin
, in case the reader has finishedEOF
so there will be no more character to read. -
As of the 2) above, when the condition is evaluated after the reading operation,
if (cin >> x)
should be likeif (cin)
, refer to this link http://www.cplusplus.com/reference/ios/ios/operator_bool/ you will see that, thisif
block will return:
-
A null pointer if at least one of
failbit
orbadbit
is set. Some other value otherwise (for C++98 standard). -
The function returns false if at least one of these error flags is set, and true otherwise. (for C++11 standard)
Solution 9 - C++
because cin is an object of class, read more on http://www.cplusplus.com/reference/iostream/cin/ .