C
LordJaxom schrieb:
Genauso wie CStoll wollte ich es zunächst auch posten, habe es dann aber ausprobiert und es kam "Müll" heraus. Meine Vermutung:
Das ganze ist undefiniert, da das erzeugte Temporary unmittelbar nach dem Funktionsaufruf, in dem es genutzt wurde gelöscht werden darf. Und jener Funktionsaufruf ist operator<<( ostream&, const char* ). D.h. schon beim zweiten operator<<, spätestens aber beim Cast, existiert der ostringstream schon garnicht mehr. Der Compiler "weiss" ja nicht, dass operator<< genau den ostream wieder zurückgibt, den er erhalten hat...
nein. temporaries werden erst am ende eines vollständigen ausdrucks zerstört. tatsächlich funktioniert
myLog.write( static_cast< std::ostringstream* >( &( std::ostringstream() << " Value: " << 12.5f ) )->str() );
genauso wie es sein muss (und ist alles andere als undefiniert. dass dabei nicht das herauskommt, was man auf den ersten blick erwarten würde, liegt an einem designfehler der iostreams.
std::ostringstream()
ist ein rvalue; folglich werden in
std::ostringstream() << " Value: "
überladungen des operators<<, die keine memberfunktionen von ostringstream sind, nicht brücksichtigt (da diese alle eine referenz auf non-const als linken parameter haben). dummerweise sind die standardüberladungen für diesen operator allerdings als memberfunktionen deklariert, und es gibt hier ein match für
ISO/IEC 14882:2003 27.6.2.1 schrieb:
basic_ostream<charT,traits>& operator<<(const void* p);
Ab dem zweiten operator << in diesem ausdruck spielt das keine rolle mehr, denn dann ist der linke operand ein lvalue und alle überladungen werden gleich behandelt.
myLog.write( static_cast< std::ostringstream& >( const_cast< std::ostream& >( static_cast< const std::ostream& >( std::ostringstream() ) ) << " Value: " << 12.5f ).str() );
könnte man nutzen; den code sollte man dann aber lieber niemandem zeigen (je nachdem, wie temporaries an referenzen auf const beim eingesetzten compiler gebunden werden, könnte das sogar undefiniertes verhalten sein)
edit: einfacher wäre noch der aufruf einer anderen memberfunktion, die in diesem zusammenhang keinen effekt hat. das ist dann in jedem falle auch wohldefiniert:
myLog.write( static_cast< std::ostringstream& >( std::ostringstream().flush() << "Value: " ).str() );