passing string stream by refernce

I'm trying to write a message log function, but am struggling to do it efficiently.

The way I have it now, I am building a string stream and passing it to a function. The function writes the message to a file. Then, I have to clear out the stringstream for the next message. Basically its looks like:

ss << "ERROR: " << text_string << " RC: " << intRc;
LogMessage(ss.str());
ss.str("");
ss.clear();

ss << "INFO: " << text_string << " RC: " << intRc;
LogMessage(ss.str());
ss.str("");
ss.clear();

and so on and so on.

The problem is, it just seems like a lot of reuse of code. I'd prefer to pass the stringstream by reference, then clear the contents in the function so it is all done once. However, it doesn't appear that passing a stringstream by reference is supported.

Is there another option?

What error message are you getting when trying to pass a stringstream by reference? The following works for me in g++ (the reference is NOT a const, because LogMessage() clears the stream after using it...):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <sstream>

void
LogMessage( std::stringstream& s )
{
  std::cout << s.str() << std::endl;

  s.str("");
  s.clear();
}

int main( int ac, char *av[] )
{
  std::stringstream s;

  s << "Hello" << "World" << 42;

  // flushes stringstream
  LogMessage( s );

  s << "Foo" << "Bar?";
  LogMessage( s );

  return 0;
}
Last edited on
Here's an option:

Make LogMessage a class and then overload the << operator with the LogMessage class. You will need to also overload the iomanip manipulators etc.

Example from Romai (http://cplusplus.com/forum/general/53222/)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <iostream>

class logger {
public:

    logger( std::ostream& os_, unsigned mask_ = 0 );


    //this allows you to do things like :
    //logger log(std::cout);
    //log(123);
    //and it returns a logger class so you can chain << to this as well. (read below for explanation)
    logger& operator()(unsigned mask_);



    void setmask(unsigned mask_);

    //functions declared with the friend keyword are not member functions,
    //but can see private members of the enclosing class
    template<class T>
    friend logger& operator<<( logger& log, const T& output );

private:

    std::ostream& os;
    unsigned mask;

};

logger::logger( std::ostream& os_, unsigned mask_ ) : os(os_), mask(mask_) {}

logger& logger::operator()(unsigned mask_) {
    setmask(mask_);
    return *this;
}

void logger::setmask(unsigned mask_) {
    mask = mask_;
}

//return type is logger& because you want to be able to chain <<() calls : (log << text1 << numbers << blahblah;)
//so :
//(log) has the type logger, so we can call operator<<()
//(log << text1) also has the type logger, we still can call operator<<() ( in fact it is the same logger instance (log) )
//and so on..
template<class T>
logger& operator<<( logger& log, const T& output ) {
    //see? normal function, but has access to log.mask and log.os because of friend declaration above
    log.os << "Mask(" << log.mask << ") : " << output << std::endl; 
    return log;
}

int main() {
    logger log(std::cout);

    log << "Hi";
    log(123) << "Hello";

    return 0;
}
.... there is no error???

hmm.... not sure what I was doing wrong, I thought I coded it almost exactly as you have it, and it didn't work. Just went back, recoded and it was fine.

Thank you for the help though.
Topic archived. No new replies allowed.