Disclaimer: This question is for understanding. I'll use boost::lexical_cast
in the field. It has sort of come up in the real world in places, though.
Take the following attempt at an "inline" lex-cast approach:
#include <string>
#include <sstream>
#include <iostream>
int main()
{
const std::string s = static_cast<std::ostringstream&>(
std::ostringstream() << "hi" << 0
).str();
std::cout << s;
}
The result is something like 0x804947c0
, because the operator<<
that works with "hi"
is a free function whose LHS must take std::ostream&
†, and temporary std::ostringstream()
can't bind to a ref-to-non-const
. The only remaining match is the operator<<
that takes const void*
on the RHS††.
#include <string>
#include <sstream>
#include <iostream>
int main()
{
const std::string s = static_cast<std::ostringstream&>(
std::ostringstream() << 0 << "hi"
).str();
std::cout << s;
}
The result is "0hi"
.
This mostly makes sense, because the operator<<
that takes int
is a member function of base ostream
††† and, as such, is fine with being invoked on the temporary. The result of that operation is a reference to the ostream
base, to which the next operator<<
is chained, i.e. read it as (std::ostringstream() << 0) << "hi"
.
But why then does that operation on "hi"
go on to yield the expected result? Isn't the reference on the LHS still a temporary?
Let's focus on C++03; I'm told that the first example may actually work as "intended" in C++11 due to the catch-all operator for rvalues.
† [C++03: 27.6.2.1]: template<class charT, class traits>
basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&,charT*);
†† [C++03: 27.6.2.1]: basic_ostream<charT,traits>& operator<<(const void* p);
††† [C++03: 27.6.2.1]: basic_ostream<charT,traits>& operator<<(int n);