Why does cout print "2 + 3 = 15" in this snippet of code?
As Igor says, you get this with a C++11 library, where std::basic_ios
has the operator bool
instead of the operator void*
, but somehow isn't declared (or treated as) explicit
. See here for the correct declaration.
For example, a conforming C++11 compiler will give the same result with
#include <iostream>
using namespace std;
int main() {
cout << "2+3 = " <<
static_cast<bool>(cout) << 2 + 3 << endl;
}
but in your case, the static_cast<bool>
is being (wrongly) allowed as an implicit conversion.
Edit: Since this isn't usual or expected behaviour, it might be useful to know your platform, compiler version, etc.
Edit 2: For reference, the code would usually be written either as
cout << "2+3 = "
<< 2 + 3 << endl;
or as
cout << "2+3 = ";
cout << 2 + 3 << endl;
and it's mixing the two styles together that exposed the bug.
Whether intentionally or by accident, you have <<
at the end of the first output line, where you probably meant ;
. So you essentially have
cout << "2+3 = "; // this, of course, prints "2+3 = "
cout << cout; // this prints "1"
cout << 2 + 3; // this prints "5"
cout << endl; // this finishes the line
So the question boils down to this: why does cout << cout;
print "1"
?
This turns out to be, perhaps surprisingly, subtle. std::cout
, via its base class std::basic_ios
, provides a certain type conversion operator that is intended to be used in boolean context, as in
while (cout) { PrintSomething(cout); }
This is a pretty poor example, as it's difficult to get output to fail - but std::basic_ios
is actually a base class for both input and output streams, and for input it makes much more sense:
int value;
while (cin >> value) { DoSomethingWith(value); }
(gets out of the loop at end of stream, or when stream characters do not form a valid integer).
Now, the exact definition of this conversion operator has changed between C++03 and C++11 versions of the standard. In older versions, it was operator void*() const;
(typically implemented as return fail() ? NULL : this;
), while in newer it's explicit operator bool() const;
(typically implemented simply as return !fail();
). Both declarations work fine in a boolean context, but behave differently when (mis)used outside of such context.
In particular, under C++03 rules, cout << cout
would be interpreted as cout << cout.operator void*()
and print some address. Under C++11 rules, cout << cout
should not compile at all, as the operator is declared explicit
and thus cannot participate in implicit conversions. That was in fact the primary motivation for the change - preventing nonsensical code from compiling. A compiler that conforms to either standard would not produce a program that prints "1"
.
Apparently, certain C++ implementations allow mixing and matching the compiler and the library in such a way that produces non-conforming outcome (quoting @StephanLechner: "I found a setting in xcode which produces 1, and another setting that yields an address: Language dialect c++98 combined with "Standard library libc++ (LLVM standard library with c++11 support)" yields 1, whereas c++98 combined with libstdc (gnu c++ standard library) yields an address;"). You can have a C++03-style compiler that doesn't understand explicit
conversion operators (which are new in C++11) combined with a C++11-style library that defines the conversion as operator bool()
. With such a mix, it becomes possible for cout << cout
to be interpreted as cout << cout.operator bool()
, which in turn is simply cout << true
and prints "1"
.