4

I have a compiler error with Visual Studio 2013 (while Xcode 6.2 compiles) which I can't make any sense of:

following example code is an abstract, reduced excerpt from a format conversion:

#include<sstream>
void main(...){
    (std::ostringstream()<<0).str();
}

while following version compiles:

#include<sstream>
void main(...){
    (std::ostringstream()).str();
}

context:

std::string result=(std::ostringstream()<<value).str(); 

what do I miss here? Thanks!

raketa
  • 43
  • 1
  • 3
  • thanks, for the suggestion, yes, the post was unclear on that, but, yes, has been included before . – raketa Apr 20 '15 at 10:03

2 Answers2

5

The error message is error C2039: 'str': is not a member of 'std::basic_ostream<char,std::char_traits<char>>'. It's complaining that str is missing in std::basic_ostream<char,std::char_traits<char>> aka std::ostream, not std::ostringstream.

std::ostringstream's operator<< still returns std::ostream& (it inherits these operators from std::ostream), which has no str() member.

Clang/libc++ (which is what Xcode uses) implements an extension in its rvalue stream insertion operator that

  1. Makes it a better match for rvalue streams compared to the inherited member operator<<s, and
  2. returns a reference to the stream as is, without conversion to std::ostream&.

Together this made your code compile in Xcode.

To call .str(), you can manually static_cast (std::ostringstream()<<value) back to std::ostringstream& (use either std::ostringstream && or const std::ostringstream& for libc++ compatibility, since its rvalue stream insertion operator returns an rvalue reference to the stream).

T.C.
  • 133,968
  • 17
  • 288
  • 421
  • thanks everybody, thats working! What a fast solution! It was all my fault wrongly reading the error message: it must read "str() is not a member of std::ostream" Thanks for pointing that out and providing the cast solution! – raketa Apr 20 '15 at 10:30
  • to compile with clang as well, a const is needed: static_cast(std::ostringstream()< – raketa Apr 20 '15 at 10:49
0

From my compiler, it actually says sst.cpp(3) : error C2039: “str”: is not a member of “std::basic_ostream<char,std::char_trait s<char>>”. Note that it is about ostream instead of ostringstream. The << is an operator defined for ostream (std::ostream::operator<<, you can refer to this).

So you can actually cast ostream back to ostringstream using static_cast<>, since the returned object is actually of a latter class, like the following code:

#include<sstream>
void main(...){
    (static_cast<std::ostringstream&>(std::ostringstream() << 0)).str();
}

will compile.

Chazeon
  • 546
  • 2
  • 14
  • No, it won't compile. – T.C. Apr 20 '15 at 10:13
  • Heh, VS2013 is even more broken than I thought. The cast should be to `std::ostringstream &`. It doesn't actually work properly AFAICT, though (check what `str()` returns). – T.C. Apr 20 '15 at 10:20
  • @T.C. Using `std::ostream const&` should work without a hitch. – Konrad Rudolph Apr 20 '15 at 10:21
  • @KonradRudolph Huh? I don't think so. – T.C. Apr 20 '15 at 10:22
  • Yeah that's a real problem, updated my code. Thanks for corrections. – Chazeon Apr 20 '15 at 10:25
  • Thanks as well! You are correct! The casting solution works! I am sorry I can't upvote yet (newbie) – raketa Apr 20 '15 at 10:33
  • @T.C. Why not? The temporary is definitely alive until the end of the expression. In fact, the non-`const` version works, too; I initially thought it shouldn’t work because it’s attempting to bind a temporary to a non-`const` reference, which is forbidden. However, no binding is taking place here. The only problem with this code is that `void main()` is an illegal signature in C++. – Konrad Rudolph Apr 20 '15 at 11:09
  • @KonradRudolph Wait, did you mean `ostream` or `ostringstream`? – T.C. Apr 20 '15 at 17:14
  • @T.C. Argh. The latter. – Konrad Rudolph Apr 20 '15 at 18:15