HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Delayed output stream "manipulator"

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
delayedoutputmanipulatorstream

Problem

I was just playing around with some code and had the idea about writing some kind of ostream manipulator to delay the output of characters in a typewriter like style.

The focus was mostly on how to use it and was inspired by std::fixed or std::setprecision.

Overall it works pretty well. I just want to make sure that I didn't miss anything that may backfire any time.

The code is just for playing around and doesn't have a real use case (yet).

#include 
#include 
#include 
#include 

namespace manip
{
    struct delayed : std::ostream, std::streambuf
    {
        std::ostream* m_postream;
        std::chrono::milliseconds m_ms;

        delayed(std::chrono::milliseconds ms)
            : std::ostream(this)
            , m_postream(nullptr)
            , m_ms(ms)
        {}

        delayed(std::ostream& o, std::chrono::milliseconds ms)
            : std::ostream(this)
            , m_postream(&o)
            , m_ms(ms)
        {}

        int overflow(int c) override
        {
            std::this_thread::sleep_for(m_ms);
            if (m_postream)
            {
                (*m_postream) (&o);
        if (delayed_ostream)
        {
            d.m_postream = delayed_ostream->m_postream;
        }
        else
        {
            d.m_postream = &o;
        }
        return d;
    }
}

int main()
{
    using namespace std::literals;
    using namespace manip;

    std::cout 
        << delayed(200ms) << "Wake up Neo."             << delayed(1100ms) << std::endl
        << delayed(200ms) << "The Matrix has you."      << delayed(3100ms) << std::endl
        << delayed(200ms) << "Follow the white Rabbit." << delayed(1100ms) << std::endl;
}


As it seems my intention on what delayed should do and how it works weren't very clear. So here is what the example will do as instructions:

```
//delayed(200ms) is passed to the stream: delay all following characters by 200ms

//delayed(1100ms) is passed to the stream: delay all following characters by 1100

Solution

I found one improvement myself by altering the operator<< function into:

std::ostream& operator(&o);
    if (d.m_ms == 0ms)
    {
        if (delayed_ostream)
        {
            return *delayed_ostream->m_postream;
        }
        else
        {
            return o;
        }
    }
    if (delayed_ostream)
    {
        d.m_postream = delayed_ostream->m_postream;
    }
    else
    {
        d.m_postream = &o;
    }
    return d;
}


This will minimize the effect of delayed when it is used to disable the delay by using delayed(0ms).

Example:

std::cout << delayed(200ms) << "Slow..." << delayed(0ms) << "Fast..." << delayed(200ms) << "Slow..." << std::endl;


The part "Fast..." will be printed immediately without any indirection through the delay object.

Code Snippets

std::ostream& operator<<(std::ostream& o, delayed&& d)
{
    using namespace std::literals;
    delayed* delayed_ostream = dynamic_cast<delayed*>(&o);
    if (d.m_ms == 0ms)
    {
        if (delayed_ostream)
        {
            return *delayed_ostream->m_postream;
        }
        else
        {
            return o;
        }
    }
    if (delayed_ostream)
    {
        d.m_postream = delayed_ostream->m_postream;
    }
    else
    {
        d.m_postream = &o;
    }
    return d;
}
std::cout << delayed(200ms) << "Slow..." << delayed(0ms) << "Fast..." << delayed(200ms) << "Slow..." << std::endl;

Context

StackExchange Code Review Q#121547, answer score: 2

Revisions (0)

No revisions yet.