Returning an std::ostream by value

Greetings.

I'm writing a multi-threaded logging library and need to be able to return-by-value a new subclass of std::ostream from a factory-like function. It boils down to this:

1
2
3
4
5
6
7
8
9
class MesgStream: public std::ostream {...};

class MesgFacility {
    MesgStream *stream;
public:
    MesgStream clone() {
        return *stream; //return a copy
    }
};


Of course that doesn't work because the copy c'tor for std::ios_base is private. This works:

1
2
3
MesgStream& clone() {
    return *new MesgStream(*this);
}


but then the user is responsible for eventually deleting it (directly or by another call into the library), and I want that to be automatic at the end of the returned value's scope.

I haven't shown everything. What I call clone() here is actually a bit more complex in the real library: it deals with incrementally created messages, redirecting output, multi-threading, etc by manipulating objects that inherit from std::streambuf.

Is there a way to return an std::ostream by value, or another way to accomplish the same goals?
> Is there a way to return an std::ostream by value

Yes. In C++11, streams are moveable (though not copyable).

Note: We would need a conforming implementation of the standard library.
For instance LLVM's or Microsoft's implementations are fine; GNU's is not.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <sstream>
#include <utility>

std::ostringstream foo()
{
    std::ostringstream stm ;
    return std::move(stm) ;
}

int main()
{
    auto stm = foo() ;
    stm << "hello " << 1 << ' ' << 2 ;
    std::cout << stm.str() << '\n' ;
}

http://coliru.stacked-crooked.com/a/1264678aaa3045b8
Instead of directly returning the MesgStream you could return a wrapper class that contains the pointer to your stream and whose destructor would delete it (for example a std::unique_ptr).
I considered wrapping a pointer, but the drawback is that then the user then needs to dereference the wrapper in order to use all the operator<< that are already defined for std::ostream.

User would need to do something like this:
1
2
Wrapper wrapper = mesgFacility->clone();
*wrapper <<"stuff";

rather than
1
2
Stream stream = mesgFacility->clone();
stream <<"stuff"

But perhaps this will be my best option for portability in light of JLBorges' reply.
Topic archived. No new replies allowed.