0

I have a logging class with a std::stringstream member. I use it's output << overloading to get a nice easy means for catching all the data types std::stringstream gives me for free.

Here's the problem. After sending data into the stream, I want an easy way to flush it automatically to my destination (which is variable/dynamic in nature).

std::ostream will "auto flush" if you send an endl down it. That's and acceptable solution I would duplicate.

How can I implement that myself? Note that I don't want to override every operator<<() overload in std::stringstream!

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
BuvinJ
  • 10,221
  • 5
  • 83
  • 96
  • Can't you just call `stream.flush()` after you add data to the stream? – NathanOliver Mar 02 '17 at 18:19
  • 4
    _"Note that I don't want to override every << overload in std::stringstream!"_ Use a template overload like `std::stringstream` does? – πάντα ῥεῖ Mar 02 '17 at 18:19
  • 1
    Possible duplicate of http://stackoverflow.com/questions/16605233/how-to-disable-buffering-on-a-stream – Captain Obvlious Mar 02 '17 at 18:20
  • 3
    How is that a dupp? – ThomasMcLeod Mar 02 '17 at 18:20
  • 2
    @Captain That's a bit far fetched. – πάντα ῥεῖ Mar 02 '17 at 18:20
  • @ThomasMcLeod Because his primary goal is to avoid buffering and output the string as early as possible. The linked dupe addresses that. – Captain Obvlious Mar 02 '17 at 18:21
  • You might just need to overload the types that you need. – ThomasMcLeod Mar 02 '17 at 18:21
  • @CaptainObvlious I read it as they want to enable auto flushing, not that they want to stop it. – NathanOliver Mar 02 '17 at 18:22
  • @Captain Well, let's 1st ask how OP actually subclassed, and then discuss what entry points can be overridden for a `std::ostream` – πάντα ῥεῖ Mar 02 '17 at 18:23
  • 3
    How about you just have the `stringstream` as a member and define your own `operator <<(T &&t)` that `forward`s it to the `stringstream` and then `flush`es? – nwp Mar 02 '17 at 18:24
  • 2
    Please post your code – ThomasMcLeod Mar 02 '17 at 18:25
  • @Thomas ^^ Exactly that's what's missing here! – πάντα ῥεῖ Mar 02 '17 at 18:26
  • @nwp, thanks a template I suppose – ThomasMcLeod Mar 02 '17 at 18:27
  • 1
    I'm tempted to answer that this problem can be solved with an overridden [`std::basic_streambuf`](http://en.cppreference.com/w/cpp/io/basic_streambuf), rather than inheriting `std::ostringstream`. – πάντα ῥεῖ Mar 02 '17 at 18:36
  • First. I cannot just use stream.flush(). That will do nothing for my use case. The stream is just a place to store the data. I then do various things with it... – BuvinJ Mar 02 '17 at 19:01
  • The answer from nwp is interesting, but I'm not sure that will be clean. In order to use class "T", I have to then declare what I'm sending into the steam all the time with an addition, no? – BuvinJ Mar 02 '17 at 19:03
  • It takes a lot work to post the code. I'm not looking to post piles and piles of proprietary code, which is mostly filled with irrelevant parts to it. I would have to create a an example. There's nothing meaningful anyway to gain from that. I have a streamstream member and an accessor to it. I use what the class gives me for feed to free data into it. Then, I get at the data via the stream.str() function. – BuvinJ Mar 02 '17 at 19:07
  • 1
    I'm going to give the answer from Anon Mail a shot... – BuvinJ Mar 02 '17 at 19:09
  • @BuvinJ _" I'm not looking to post piles and piles of proprietary code, which is mostly filled with irrelevant parts to it."_ That's why you're required to work down your problem to a [MCVE] here. – πάντα ῥεῖ Mar 02 '17 at 19:37
  • Thankfully, Anon Mail understood my needs exactly and rapidly posted a solution without me having to go through that. – BuvinJ Mar 02 '17 at 20:53

2 Answers2

1

I've done a similar thing. What I do is use an unnamed class instance to consume the output and put the flushing in the destructor. Something like this:

int i = 0;
MyClass() << "This is a log message containing an int: " << i;
// here, the class destructs and does whatever you need to do to flush the stream
Anon Mail
  • 4,660
  • 1
  • 18
  • 21
1

Instead of subclassing std::stringstream, it's prefered to use composition (see Composition over inheritance).

With this, your class would look like this:

class Log{

    std::stringstream _stream;

    [...] // Constructor and other class logic

    public:
    Log& operator<<(string s){
        _stream << s << endl;
        return *this;
    }

};
ZeroUltimax
  • 256
  • 1
  • 9
  • Thanks. I already have it as a member though, and my Log class is not what I << the data into. I send data directly to the member via an accessor. Ignoring that, your solution would force me to overload every version of the stringstream << function. That negates the entire purpose of using it! All I want it for is those dozens of "free" functions. – BuvinJ Mar 02 '17 at 19:33