Connecting Tech Pros Worldwide Forums | Help | Site Map

drop in replacement for stringstream that compiles to nothing

Member
 
Join Date: Nov 2007
Posts: 46
#1: Jul 7 '08
hi

I find myself using stringstream all over my code just to build debug messages that I may or may not write to cout later. that is very comfortable while developing but is generally useless for productive code.

so I would like to have some construct that the compiler will remove in the case of NDEBUG. but I dont want to write #ifndef NDEBUG everywhere.

I have tried with this, but seemingly the compiler still cant completely remove NullStream because if I raise the loopcount to something like 10e7 it takes 3 seconds (with MSVS 2005 /O2, even longer with cygwin/gcc344 or ubuntu7.1/gcc413 -O3)

Expand|Select|Wrap|Line Numbers
  1. #include <iostream>
  2. #include <string>
  3. #include <sstream>
  4. using namespace std;
  5.  
  6.  
  7. class NullStream
  8. {
  9. public:
  10.     inline const NullStream& operator<< ( const string & s ) const
  11.     {
  12.         return *this;
  13.     }
  14.     inline const NullStream& operator<< ( int& i ) const
  15.     {
  16.         return *this;
  17.     }
  18.     inline const NullStream& operator<< ( unsigned int& i ) const
  19.     {
  20.         return *this;
  21.     }
  22. };
  23. inline ostream& operator<<( ostream& o, const NullStream& n)
  24. {
  25.     return o;
  26. }
  27. inline ostream& operator<<( ostream& o, const stringstream& s )
  28. {
  29.     o << s.str();
  30.     return o;
  31. }
  32. #ifdef NDEBUG
  33.     typedef NullStream LogStream;
  34. #else
  35.     typedef ostringstream LogStream;
  36. #endif
  37.  
  38.  
  39.  
  40.  
  41. void main_logstream()
  42. {
  43.     cout << __FUNCTION__ << "\n";
  44.     LogStream buf;
  45.  
  46.     double clock_begin = clock();
  47.  
  48.     for ( unsigned int i = 0 ; i < 10e7 ; i++ )
  49.     {
  50.         buf << i << " ";
  51.     }
  52.     cout << "buffer: " << buf << "\n";
  53.     cout << "time: " << ( ( clock() - clock_begin ) / CLOCKS_PER_SEC ) << " s\n";
  54. }
  55.  

I had expected that the compiler should be able to see that the body of that loop only consistst of a couple of calls to functions with empty bodies and thus the whole loop can be removed.

Anybody any suggestions?

Member
 
Join Date: Nov 2007
Posts: 46
#2: Jul 7 '08

re: drop in replacement for stringstream that compiles to nothing


uups, seemingly the compiler wont even remove

Expand|Select|Wrap|Line Numbers
  1. for ( unsigned int i = 0 ; i < 10e7 ; i++ )
  2. {
  3.     (void)0;
  4. }
  5.  
am I asking for too much?

CORRECTION: Sorry, that was wrong, for(...){ (void)0; } does get removed!
Member
 
Join Date: Nov 2007
Posts: 46
#3: Jul 22 '08

re: drop in replacement for stringstream that compiles to nothing


yet another correction: seemingly the (void)0; is removed but the (then empty) loop is not ... anyways ...

back to my orignial question - just in case anybody cares - ive not managed to get something that can be #define'd to (void)0 that can be used like a stream but now I have a bunch of macros like

Expand|Select|Wrap|Line Numbers
  1. #define logstream2( stream, m1, m2 ) \
  2.     if (true) { \
  3.         ostream& log_stream = stream; \
  4.         log_stream  << m1 << m2; \
  5.     } else (void)0
  6.  
(and also logstream1, logstream3, etc)

This hasnt got the same interface as stream, ie operator<<(), but its the best I was able to achieve.
Reply