operator << for std::string in #define

P

probstm

I am using a message handler class that implements amongst others:

static void message ( std::string aHeader,
std::string aMessage,
int aTimeout = 0,
MessageType aFlag =
MSG_Information );

I then use a set of defines, e.g.:

#define USR_MSG( msg ) MSG::message( "", msg, 0, MSG_User )

The problem is now that I get a compiler error when I write

USR_MSG("The value of x is " << x);

Does anybody have a smart solution for that? I thought about rerouting
std::cout but it doesn't seem to be the best way to me.

Thanks a lot for your help,

Martin.
 
P

pmouse

I am using a message handler class that implements amongst others:

static void message ( std::string aHeader,
std::string aMessage,
int aTimeout = 0,
MessageType aFlag =
MSG_Information );

I then use a set of defines, e.g.:

#define USR_MSG( msg ) MSG::message( "", msg, 0, MSG_User )

The problem is now that I get a compiler error when I write

USR_MSG("The value of x is " << x);

Does anybody have a smart solution for that? I thought about rerouting
std::cout but it doesn't seem to be the best way to me.

Thanks a lot for your help,

Martin.

Write a string format function on your own:
string string_format( char* format, ... ) ;
then wrap vsprintf and provide a formatting routing. You can now do:

USR_MSG( string_format("The value is %d", x) );

Regards,

PQ
 
I

Ivan Vecerina

:I am using a message handler class that implements amongst others:
:
: static void message ( std::string aHeader,
: std::string aMessage,
: int aTimeout = 0,
: MessageType aFlag =
: MSG_Information );
:
: I then use a set of defines, e.g.:
:
: #define USR_MSG( msg ) MSG::message( "", msg, 0, MSG_User )
:
: The problem is now that I get a compiler error when I write
:
: USR_MSG("The value of x is " << x);
:
: Does anybody have a smart solution for that? I thought about rerouting
: std::cout but it doesn't seem to be the best way to me.

Here's a hack-ish macro that uses a stringstream for streaming,
and returns a pointer to a temporary C-string:

template<class C>
inline C& stripConstFromTemporaryRef(C const& r) { return (C&)r; }

#define STRM2CSTR( ss ) \
(:):std::eek:stringstream&) \
(stripConstFromTemporaryRef:):std::eek:stringstream()) \
<<ss )).str().c_str()


(NB: the strip... function is needed in case the first streamed
value uses a non-member << function )

Then you would define your macro as:
#define USR_MSG(msg) MSG::message( "", STRM2CSTR(msg), 0, MSG_User )

Of course this adds some run-time overhead in the simple case
where a static string is to be streamed. There should be a way
to use some smart template tricks to optimize-out the simple
case, but I have never bothered looking into this.


I hope this helps,
Ivan
 
P

peter koch

I am using a message handler class that implements amongst others:

static void message ( std::string aHeader,
std::string aMessage,
int aTimeout = 0,
MessageType aFlag =
MSG_Information );
You should not pass by value here use std::string const& for aHeader
and aMessage. It also appears that you name the class MSG wwhich is
against the stylistic recommendations of C++ where all-caps is
reserved for macroes. Following these recommendations might save you
lots of trouble later on.
I then use a set of defines, e.g.:

#define USR_MSG( msg ) MSG::message( "", msg, 0, MSG_User )

Don't do that: macroes are better avoided. Better is to use a
function, e.g.

inline void user_msg(std::string const& msg)
{
MSG::message( "", msg, 0, MSG_User );
}
(You could have it in your MSG-class if you find that is sensible. (To
me it looks as if you should rather use a namespace).
The problem is now that I get a compiler error when I write

USR_MSG("The value of x is " << x);

Does anybody have a smart solution for that? I thought about rerouting
std::cout but it doesn't seem to be the best way to me.
I would probably spend an extra line and use a stringstream here.
Otherwise a macro here could be appropriate:

#define USR_MSG(text_) { std::stringstream s; s << text_;
user_msg(s.str()); }

/Peter
 
G

Greg Herlihy

I am using a message handler class that implements amongst others:

static void message ( std::string aHeader,
std::string aMessage,
int aTimeout = 0,
MessageType aFlag =
MSG_Information );

I then use a set of defines, e.g.:

#define USR_MSG( msg ) MSG::message( "", msg, 0, MSG_User )

The problem is now that I get a compiler error when I write

USR_MSG("The value of x is " << x);

Does anybody have a smart solution for that? I thought about rerouting
std::cout but it doesn't seem to be the best way to me.

The C++ way would be to write an inline function instead of macro:

inline void USR_MSG( const std::string& msg )
{
MSG::message( "", msg, 0, MSG_USER);
}

Now the program may call USR_MSG in a variety of ways, including:

USR_MSG( "This is a message" );

and:

std::string x("5");

USR_MSG( "The value of x is " + x );

Greg
 
J

James Kanze

:I am using a message handler class that implements amongst others:
: static void message ( std::string aHeader,
: std::string aMessage,
: int aTimeout = 0,
: MessageType aFlag =
: MSG_Information );
: I then use a set of defines, e.g.:
:
: #define USR_MSG( msg ) MSG::message( "", msg, 0, MSG_User )
:
: The problem is now that I get a compiler error when I write
:
: USR_MSG("The value of x is " << x);
:
: Does anybody have a smart solution for that? I thought about rerouting
: std::cout but it doesn't seem to be the best way to me.

Here's a hack-ish macro that uses a stringstream for streaming,
and returns a pointer to a temporary C-string:
template<class C>
inline C& stripConstFromTemporaryRef(C const& r) { return (C&)r; }
#define STRM2CSTR( ss ) \
(:):std::eek:stringstream&) \
(stripConstFromTemporaryRef:):std::eek:stringstream()) \
<<ss )).str().c_str()
(NB: the strip... function is needed in case the first streamed
value uses a non-member << function )

In the case of ostringstream, you can use the even hackier:

(std::eek:stringstream().flush() << ss)

In such cases, I'll either have message take an std::eek:stream&
(which it dynamic_casts to std::eek:stringstream in order to
extract the text), or I'll use the decorator pattern (or
proxy---I'm never really sure which it is), with something like:

class Collector
{
public:
template< typename T >
Collector& operator<<( T const& v )
{
myStream << v ;
return *this ;
}
std::string str()
{
return myStream.str() ;
}
private:
std::eek:stringstream myStream ;
} ;

(For such a simple case, just using the ostringstream directly,
and calling flush, is probably preferable. In practice, my
"Collector" will different target streams depending on the
level of tracing which has been activated, and such things.)

I've generally wrapped this in a macro anyway, because every
time I've wanted it, I've also wanted automatic insertion of
__FILE__ and __LINE__.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,754
Messages
2,569,525
Members
44,997
Latest member
mileyka

Latest Threads

Top