Odd behavior with ostringstream

I was trying to come up with a smart way to combine various things into one string argument for a function, without using explicitly ostringstream . I thought:

 #define OSS(...) \ dynamic_cast<std::ostringstream const&>(std::ostringstream() << __VA_ARGS__).str() 

However, given:

 void f( string const &s ) { cout << s << endl; } int main() { char const *const s = "hello"; f( OSS( '{' << s << '}' ) ); ostringstream oss; oss << '{' << s << '}'; cout << oss.str() << endl; } 

it prints at startup:

 123hello} {hello} 

where 123 is the ASCII code for } . Why is using a macro wrong?

FYI: I am currently using g ++ 4.2.1 on Mac OS X as part of Xcode 3.x.


Solution now i'm using

 class string_builder { public: template<typename T> string_builder& operator,( T const &t ) { oss_ << t; return *this; } operator std::string() const { return oss_.str(); } private: std::ostringstream oss_; }; #define BUILD_STRING(...) (string_builder(), __VA_ARGS__) using namespace std; void f( string const &s ) { cout << s << endl; } int main() { char const *const s = "hello"; f( BUILD_STRING( '{', s, '}' ) ); } 
+4
source share
2 answers

The best thread-safe solution without involving a bulky macro.

The initial function call is as follows:

 f( OSS( '{' << s << '}' ) ); 

How about whether the call is just that:

  f(stringbuilder() << '{' << s << '}' ); 

where stringbuilder is implemented as:

 struct stringbuilder { std::ostringstream ss; template<typename T> stringbuilder & operator << (const T &data) { ss << data; return *this; } operator string() { return ss.str(); } }; void f( string const &s ) { cout << s << endl; } 

Test:

 int main() { char const *const s = "hello"; f(stringbuilder() << '{' << s << '}' ); } 

Output:

 {hello} 

Online Demo: http://ideone.com/QHFf4

+3
source

std::ostringstream() is temporary, so it can only be associated with const references. The autonomous operator <(which accepts not const links as the first argument) is not considered, but only one member. The best match in them for char converts char to int.

These problems often occur with string literals, whose address is then displayed.

To solve the problem, the trick is to find a way to convert the temporary into a link. The operator<< element does this, but only one for the manipulator does this without a side effect, and only if the manipulator is noop-flush can you use it. Flash members and recordings are also candidates. For example,

 #define OSS(...) \ dynamic_cast<std::ostringstream const&>(std::ostringstream().flush() << __VA_ARGS__).str() 
+5
source

Source: https://habr.com/ru/post/1348136/


All Articles