 |
|
 |
Hi Taka,
I find that if the first portion of the msg is a cstring like
std::cout << MAKE_STRING( "The answer is: " << theAnswer ) ;
a memory address is printed along with the value of 'theAnswer'.
Output:
004610D842
Why is that?
The temporary fix I am using is
MAKE_STRING( std::string("The answer is: ") << theAnswer ) ;
Thanks,
An
|
|
|
|
 |
|
 |
I have solved that this way:
#define MAKE_STRING( msg ) ( ((std::ostringstream&)(std::ostringstream() \
<< std::dec << msg)).str() )
Compiler was Apple GCC 4.0
modified on Monday, July 6, 2009 4:33 AM
|
|
|
|
 |
|
 |
There is (rightly) a compiler warning that is generated from this code (I had done the same thing myself).
The problem is that the only reason this works is because by convention, the operator<< returns a reference to the stream passed in. The compiler is rightfully wary of casting the base std::ostream to it's implementation st::ostringstream.
There is no nice way of getting round this, unfortunately. Here's my version, designed for LPCTSTR arguments:
#define S_(string)\
(reinterpret_cast<const std::basic_ostringstream<TCHAR> &> (std::basic_ostringstream<TCHAR>() \
<< string << std::ends)).str().c_str()
//.ichael G.
|
|
|
|
 |
|
 |
The nice way around this is to get the standards committee to do something useful for once and include conversions in the std::string implementation. How difficult would it be to implement something for the basic data types?
A cynic is a man who, when he smells flowers, looks around for a coffin. -H.L. Mencken
|
|
|
|
 |
|
 |
I never worked with streams, so, maybe I'm missing the big picture, but, why don't you get rid of those ugly macros by something like this...
class s : public ostringstream { public: operator string() const { return str(); } operator const char *() const { return str().c_str(); } template<typename AA> s &operator <<(const AA &str) { *static_cast<ostringstream *>(this) << str; return *this; } }; ... string aa = s() << "abc" <<...; Of course, it should be considered whether to leave the const char * operator, since it's valid only in the current statement. - Goran.
|
|
|
|
 |
|
 |
That is cool! After all these years of OO programming, I'm still trying to shake off my C/assembly roots
However, I have to admit I still prefer the macro. Yes, it's way ugly but only in the definition. When using it, it's really clean. It stands out in the code that something slightly unusual is going on and doesn't require you to write anything not involved in the building of the string i.e. your solution still requires you to explicitly create the temporary stream object. In other words:
foo( MAKE_STRING( "x=" << x << " ; y=" << y ) ) ;
vs.
foo( s() << "x=" << x << " ; y=" << y ) ;
Come down taste, I guess.
Thanks for the idea.
he he he. I like it in the kitchen! - Marc Clifton (on taking the heat when being flamed)
Awasu v0.4a[^]: A free RSS reader with support for Code Project.
|
|
|
|
 |
|
 |
Of course, you can now do something like: #define MAKE_STRING_WITHOUT_PARENTHESIS_AT_ALL s()
BTW, assembly roots? Oh... Sob... Those were the times... - Goran.
|
|
|
|
 |
|
 |
he he he. I like it in the kitchen! - Marc Clifton (on taking the heat when being flamed)
Awasu v0.4a[^]: A free RSS reader with support for Code Project.
|
|
|
|
 |
|
 |
I'd suggest checking out lexical_cast from Boost (http://www.boost.org). Your example would like this with lexical cast:
using namespace std;
using namespace boost;
foo(string("x=") + lexical_cast(x) + " ; y=" + lexical_cast(y));
I think this conveys what you're doing even better and avoids macros. It also has the nice benefit that it can convert to/from anything via the wonders of iostreams... which means we can go in reverse:
int x = lexical_cast("10");
Currently lexical_cast<> isn't perfect (the biggest problem is that it doesn't handle spaces in char* style strings, including string literals, well), but there's proposed fixes that will make it in someday.
William E. Kempf
|
|
|
|
 |
|
 |
What is the advantage of this Macros ?
Is it better than f.ex using the following code ?
xstring str = xstring("The answer is: ") + xstring(theAnswer);
with
#ifdef UNICODE
typedef std::wstring xstring;
#else
typedef std::string xstring;
#endif
|
|
|
|
 |
|
 |
Your example won't work. xstring(theAnswer) won't convert the integer value into its string representation (try it - you'll get a compile error). That is the job of an ostream class, in this case, ostringstream. What the macro does is automatically create a temporary ostringstream object for you so that you don't have to worry about it.
he he he. I like it in the kitchen! - Marc Clifton (on taking the heat when being flamed)
Awasu v0.4a[^]: A free RSS reader with support for Code Project.
|
|
|
|
 |
|
 |
The boost mob have gone one better with their format lib http://www.boost.org/libs/format/doc/format.html[^]. Stops you having to do all that tedious << ios::hex gubbins.
Ryan
Computers allow you to make more mistakes than any other invention, with the possible exception of handguns and tequila.
|
|
|
|
 |
|
 |
Yuk! Thanks for the link, but yuk!
One of the great things about streams is that you don't have to worry about matching parameter values with their placeholders in a format string. The boost library seems like a step backwards!
I found it hard to leave the comfort of printf format strings, which I knew well, and move to manipulators but once I got the hang of them, it wasn't really a problem. Sometimes, streaming stuff out can result in rather long lines but if you break it up, it actually becomes much more readable e.g.
cout << "The answer: "
<< hex << setw(5) << setfill('*') << theAnswer
<< endl ;
he he he. I like it in the kitchen! - Marc Clifton (on taking the heat when being flamed)
Awasu v0.4a[^]: A free RSS reader with support for Code Project.
|
|
|
|
 |
|
 |
I was really happy about being able to use 'sprintf' again, I guess I'm just a luddite at heart
Ryan.
Computers allow you to make more mistakes than any other invention, with the possible exception of handguns and tequila.
|
|
|
|
 |
|
 |
Not to mention ostreams are potentially faster because there's no need to parse the formatting string, this is done at compile time.
I see dumb people
|
|
|
|
 |
|
 |
Here is a breakdown of stream performance.
Using fprintf and a stream both pointing to "NUL:" (bitbucket device), streams are faster by about 10-20%. However, you have to be VERY careful. If you use "endl", then streams slow down to around 2 times slower than fprintf. This is because endl does a flush of the output. This would be like calling "fflush" after every fprintf. It comes at a cost.
Now, when it comes to string streams, I have not personally tested it, so I can't give any specific values. However, someone was having a performance problem with a hash_map. He was using string streams to generate the keys. Once he changed from string streams to sprintf, the application flew like a bat out of hell. My "GUESS" is that the extra allocations and reallocations required to support the string stream might have been significant enough in his case to cause a problem.
So over all, for pure formatting power, streams are the fastest. You just have to be very careful how you use them when performance is an issue.
Tim Smith
I'm going to patent thought. I have yet to see any prior art.
|
|
|
|
 |
|
 |
Tim Smith wrote:
Once he changed from string streams to sprintf, the application flew like a bat out of hell.
And my guess would be that he was using Microsoft's implementation of the STL. Their string implemention sucks big time, particularly in cases where you are doing lots of re-allocations. I don't have the figures at hand but I ran some performance tests on a variety of STL implementations a while ago and StlPort's string was significantly faster than MSVC's. In your friend's case, giving the string buffer a chance at performing reasonably by calling reserve() would also have made a big difference.
So yes, you have to be careful. Any class that uses dynamically allocated memory is never going to stand a chance against something that uses a fixed-size buffer on the stack without some help. But it will never have buffer overruns either
he he he. I like it in the kitchen! - Marc Clifton (on taking the heat when being flamed)
Awasu v0.4a[^]: A free RSS reader with support for Code Project.
|
|
|
|
 |
|
 |
That is the whole thing. It is which evil you decide you want. About the only position I find silly are the people who say "use STL" or "use primitive C" 100% all the time. Each has strong and weak points.
He did try both (edit: I think), and STLPort didn't help. Most of my timing tests are with STLPort because I got tired of everyone saying "but Microsoft's version sucks".
Tim Smith
I'm going to patent thought. I have yet to see any prior art.
|
|
|
|
 |
|
 |
Tim Smith wrote:
It is which evil you decide you want.
I don't think it's a question of choosing between two evils, it's a question of learning to use the tools properly. The advantages of STL strings over fixed-size buffers far outweigh the problems, you just have to learn how to use reserve() properly. [edit] And find a decent implementation.
Tim Smith wrote:
but Microsoft's version sucks
And there's a reason for that: it does!
he he he. I like it in the kitchen! - Marc Clifton (on taking the heat when being flamed)
Awasu v0.4a[^]: A free RSS reader with support for Code Project.
|
|
|
|
 |
|
 |
Possibly the problem could have been that while formatting with stringstreams is pretty quick, retrieving the result from the stream is not so great as str() returns a copy of the string (i.e. has to construct a new string object and initialize it with the contents of the internal buffer).
If you then need to convert this to a C string, you have another function call (c_str()) which in many implementations has to modify the string yet again.
|
|
|
|
 |
|
 |
Tim Smith wrote:
Now, when it comes to string streams, I have not personally tested it, so I can't give any specific values. However, someone was having a performance problem with a hash_map. He was using string streams to generate the keys. Once he changed from string streams to sprintf, the application flew like a bat out of hell. My "GUESS" is that the extra allocations and reallocations required to support the string stream might have been significant enough in his case to cause a problem.
That's why I said "potentially faster" and not "faster", since I've made no tests and I don't know all the gory implementation details of STL and maybe there are some ineficiencies that I don't know.
I see dumb people
|
|
|
|
 |
|
 |
Taka Muraoka wrote:
One of the great things about streams is that you don't have to worry about matching parameter values with their placeholders in a format string. The boost library seems like a step backwards!
You don't have to "match paremeters" using Boost.Format:
cout << format("%s") % "x=" << format("%d") % x;
should work.
But this misses the point of positional placeholders. Sometimes you _NEED_ this. If you internationalize the order in which data is displayed may very well change from the order in which you specify them in code.
I'm not sure I totally like Boost.Format, but there are cases in which it's the best tool available to me.
William E. Kempf
|
|
|
|
 |
|
 |
I've made my own similar class (though it doesn't handle locales) - which I did after seeing % used in this manner in python... and it handles detecting mismatched string types.
Both these methods have their place. ostringstreams are good for creating streams of data... constructing queryies in other languages (SQL for eg)... the sprintf format has its own uses.
One important thing to remember is that internationalised strings with multiple place-holders need to be allowed to order the place holders differently.
Neither ostringstream or pure sprintf formats allow this. I believe boosts format does, as well as microsoft's FormatMessage - which uses %1 %2 %3!2.2d! instead of %s %s %2.2d.
I chose to implement this version (as well as sprintf), partly 'cause we were already using microsoft's version anyway.
//.ichael G
|
|
|
|
 |
|
|
 |
|
 |
A lot of people hate macros and the way they're often used, they're right.
But I really like them for the ability they give me to do meta-programming. I've written macros to generate code that would scare the pants off you! Horrible to set up but very convenient and time-saving.
he he he. I like it in the kitchen! - Marc Clifton (on taking the heat when being flamed)
Awasu v0.4a[^]: A free RSS reader with support for Code Project.
|
|
|
|
 |