On OS X, simple C++ program gives incorrect results (which are a result of command-line options 'c++03' vs 'c++11')

c++, linux, macos, operator-keyword, rvalue

Solution

Firstly, the expected difference in behaviour is because the `operator<<(std::ostream&, const char*)` overload (it's actually a function template specialization, but nevermind for now) has a parameter of type `std::ostream&` and an lvalue reference can only bind to an lvalue, and in your example the stream is an rvalue so that overload can't be used. In C++03 that means the only viable overload is the `std::ostream::operator<<(const void*)` member function, because member functions can be called on rvalue objects, so the string is written out as a `void*` address in hexadecimal. In C++11 there is a new `operator<<(std::ostream&&, const T&)` function template that allows writing to rvalue streams, and forwards to the `operator<<(std::ostream&, const char*)` overload, so the string is output rather than a hex address.

On GNU/Linux you are presumably using a fairly recent GCC release, which has fairly good support for C++11 in both the compiler (g++) and the standard library (libstdc++) so it has the `operator<<(std::ostream&&, const T&)` overload and everything Just Works.

On OS X you are probably using Clang with GCC's standard library, libstdc++. Xcode ships with an ancient version of GCC by default (4.2) and the standard library from GCC 4.2 doesn't support C++11, so doesn't have the `operator<<` overload for rvalue streams. Using `-std=c++0x` tells Clang to support C++11 language features (such as rvalue references), but doesn't magically make GCC 4.2's library grow C++11 code that wasn't even a twinkle in the standard committee's eye when GCC 4.2 was released. Rather than shipping a non-prehistoric libstdc++ Apple instead wrote their own standard library implementation to go with LLVM and Clang projects. Using `-stdlib=libc++` tells clang to use that libc++ standard library implementation instead of the ancient libstdc++. As libc++ was written recently it has the `operator<<` overload for rvalue references.

Problem

This simple program (when compiled on Linux) will CORRECTLY give two different answers based on whether it's compiled with `-std=c++0x` or not. Problem: I cannot reproduce the same thing on OS X (Mountain Lion, 10.8 SDK). What am I missing? ``` #include <iostream> #include <sstream> class Thing : public std::ostringstream { public: Thing() : std::ostringstream() {} virtual ~Thing() { std::cerr << str(); } }; int main(int argc, const char * argv[]) { Thing() << "Hello" << std::endl; return 0; } ``` To see what I mean, do the following (on Linux first, just to see how it should work): ``` > g++ main.cpp > ./a.out 0x401471 ``` ``` > g++ -std=c++0x main.cpp > ./a.out Hello ``` The first will print a hex address, the second will print "Hello". This is correct behavior and is because the operator `<<` resolves to two different things (there are no rvalue references in C++03 so there you go). Now, try the same thing on OS X: ``` > xcrun c++ main.cpp > ./a.out 0x10840dd88 ``` (This correctly produces the hex output.) ``` > xcrun c++ -std=c++0x main.cpp > ./a.out 0x10840dd88 ``` (Oops... still the hex output... We are in C++11x mode, but perhaps the correct headers are not being used?) NOTE: Version of the compiler is here: ``` > xcrun c++ --version Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn) Target: x86_64-apple-darwin12.2.0 Thread model: posix ``` NOTE: This is not a C++ issue per se, but rather an OS X build issue. For those who are interested, the reason that it produces different results with C++03 and C++11 is highlighted below in one of the answers.

Original source