operator << for std::string in #define

Discussion in 'C++' started by probstm@gmail.com, May 8, 2007.

  1. Guest

    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.
    , May 8, 2007
    #1
    1. Advertising

  2. pmouse Guest

    On May 8, 1:33 am, wrote:
    > 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
    pmouse, May 8, 2007
    #2
    1. Advertising

  3. <> wrote in message
    news:...
    :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
    --
    http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
    Brainbench MVP for C++ <> http://www.brainbench.com
    Ivan Vecerina, May 8, 2007
    #3
  4. peter koch Guest

    On 8 Maj, 07:33, wrote:
    > 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
    peter koch, May 8, 2007
    #4
  5. Greg Herlihy Guest

    On May 7, 10:33 pm, wrote:
    > 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
    Greg Herlihy, May 8, 2007
    #5
  6. James Kanze Guest

    On May 8, 8:35 am, "Ivan Vecerina"
    <> wrote:
    > <> wrote in message


    > news:...
    > :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__.

    --
    James Kanze (Gabi Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, May 8, 2007
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Matthias =?ISO-8859-1?Q?K=E4ppler?=

    std::string::push_back vs. std::string::operator+=

    Matthias =?ISO-8859-1?Q?K=E4ppler?=, Nov 22, 2004, in forum: C++
    Replies:
    2
    Views:
    4,116
    Jonathan Mcdougall
    Nov 23, 2004
  2. Peter Jansson
    Replies:
    5
    Views:
    6,263
    Ivan Vecerina
    Mar 17, 2005
  3. Geoffrey S. Knauth
    Replies:
    6
    Views:
    977
    Earl Purple
    Jan 18, 2006
  4. Martin T.
    Replies:
    7
    Views:
    806
    Martin T.
    Mar 10, 2008
  5. curiousEngine
    Replies:
    1
    Views:
    1,347
    James Kanze
    May 9, 2008
Loading...

Share This Page