Jump to content
  • Advertisement
Sign in to follow this  
tmunq

std::ostream question

This topic is 4873 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So, I'm making this engine. I figured it would be smart to give the engine a pointer to an std::ostream object for debugging purposes.
void Engine::StartDebug(std::ostream * stream)
{
    // ...
    _debug = stream;
    // ...
    *_debug<<"[Engine] Starting internal debugging...\n"
    // ...
}
// ...
engine->StartDebug(&stream);

I think it's sweet because the stream can be to a file (std::ofstream) or to memory (std::ostringstream) and the engine doesn't have to care. Not to mention the iostream library... Anyway, I would like to have a stream to both (memory and a file). How do I make something derived from std::ostream that would "pass the input along" to an std::ofstream and an std::ostringstream object. Something like this:
std::ofstream log_file("log.txt");
std::ostringstream log_text;
mystream log_stream;
// ...
log_stream.passalong(log_file);
log_stream.passalong(log_text);
// ...
engine->StartDebug(&log_stream);
// write everything the file "log.txt" and to the string log_text.str()...

Do you think this is a good solution, by the way?

Share this post


Link to post
Share on other sites
Advertisement
You don't need to use pointers to be able to pass in any sub-types of std::basic_i/o/iostream you can use a reference types and they should be preferred where applicable.

Anyways back to the point the only problem with that is you need to be careful with instances being destroyed by scope and since iostreams are not assignable/value types you can't store them directly in any container. Best thing to do is probably have a container of smart pointer or a pointer container to streams that have been dynamically allocated on the heap, then again it depends on your requirements.

Share this post


Link to post
Share on other sites
How do I make something derived from std::ostream that would "pass the input along" to an std::ofstream and an std::ostringstream object.

I'm not too familiar with the C++ standard library.

Or would it be smarter to be able to give the engine several stream? I think this approach seems a bit strange but it could be done easily.

Share this post


Link to post
Share on other sites
After giving it some tought, I think it's best to give the engine several streams. You could assign these with certain preferences such as what to report..

You don't need all the details in the game console but they can be usefull in the log file.

Share this post


Link to post
Share on other sites
If you want to create an ostream that writes to multipule ostreams, then you chould make a custom streambuf that can hold pointers to other streambufs and delegates any calls it receives to all of its member streambufs. ( It could also instead hold (preferably shared_) pointers to ostreams. )

You could then use it along the lines of:
multistream log;
log.add( boost::shared_ptr<std::ofstream>( new std::ofstream("outfile.txt") ) );


log.add() would use dynamic_pointer_cast<std::ostream> and dynamic_pointer_cast<std::istream> to add the streams to the vector<shared_ptr<std::istream> > and/or the vector<shared_ptr<std::ostream> > inside the multistream's multistreambuf.

For more sophisticated logging, there's a logging library that was just proposed to boost. ( The author withdraw the review, however, but is now working on another version. )

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Original post by tmunq
How do I make something derived from std::ostream that would "pass the input along" to an std::ofstream and an std::ostringstream object.

The std::ostream is responsible solely for formatting your data (and perhaps transforming it into an external code set). It sounds like what you want to do is have a streambuf that sends the formatted output to several destinations.

That's really easy to do. You just need to derive from std::streambuf and override the overflow() member function, then use the rdbuf() functions of two or more std::ostream objects to get and combine and reset the underlying streambufs.

This way, your engine needs only a single ostream.

Read Langer & Kreft for a good overview.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!