Why can one cast a std::ostream
to a void
pointer? I am not aware of any such conversion operator in std::ostream
. Code below
#include <iostream>
int main()
{
void *p = std::cout; // why does this work?
}
I'm asking this question since I've seen a placement operator new
invoked as
Foo* pFoo = new (std::cerr) Foo;
and have absolutely no idea why would one write such a thing.
PS: I am compiling with g++ 4.9.2 with or without -std=c++11
. clang++ does not accept the code.
PSS: Found out that due to the so called "safe bool problem" (see @nicebyte's answer), in pre C++11 a void*
conversion operator was defined for std::ostream
, which was then removed in C++11. However, my code compiles fine in C++11 using g++. More than that, clang++ rejects it no matter what version of the standard I use, even with -std=c++98
, although my understanding is that it should accept if compiled as pre-C++11.
Read this (your question is answered in the very last section, "The safe bool problem").
To elaborate a bit, the implementation defines an implicit conversion to void*
defined for things like std::cin
and std::cout
, just so that code like while(std::cin>>x){...}
compiles, while code like int x = std::cin;
doesn't. It's still problematic because you can write stuff like in your example.
C++11 solves this problem by introducing explicit conversions.
An explicit conversion operator looks like this:
struct A {
explicit operator B() { ... } // explicit conversion to B
};
When A has an explicit conversion to B, code like this becomes legal:
A a;
B b(a);
However, code like this is not:
A a;
B b = a;
A construct like if(std::cin)
requires cin
to be converted to bool
, the standard states that in order for the conversion to be valid in that particular case, code like bool x(std::cin);
should be "legal". Which can be achieved by adding an explicit conversion to bool
. It allows cin/cout to be used in the above context, while avoiding things like int x = std::cout;
.
For more information, refer to Bjarne's page as well as this question.
Answering only the follow-up, since nicebyte's answer is perfect for the original question.
Chances are, your gcc is set up to use libstdc++ (which hasn't changed the operator yet due it being an ABI-breaking change), and your clang is set up to use libc++ (which was from the beginning intended as a C++11 standard library and isn't quite conformant in C++98 mode - it provides a bool conversion operator that is explicit in C++11).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With