#include <cstdarg>
#include <cstdio>
#include <string>
#include <unistd.h>

class PrintContext
{
public:
    ~PrintContext()
    {
        write(1,"[debug, calling write():]\n",26);
        write(1,buffer.c_str(),buffer.size());
        buffer.clear();
    }
    PrintContext &printf(const char* format, ...)
    {
        va_list args4len, args;
        va_start(args, format);
        va_copy(args4len, args); // each va_list can only be used once, so make a copy

        // calculate length of what we want to add to the buffer
        int len = vsnprintf(NULL, 0, format, args4len);
        va_end(args4len);

        // create room for it in the buffer
        int pos = buffer.size();
        buffer.resize(pos + len);

        // add the new data to the buffer
        vsnprintf(buffer.data()+pos,buffer.size()-pos+1,format, args); // +1 because std::string makes room for null terminator
        va_end(args);

        return *this;
    }
private:
    std::string buffer;
};

int main() {
    PrintContext().printf("Hello, %s! The answer is %d\n", "John", 42);

    {
        PrintContext pc;
        pc.printf("First line (blah %g)\n", 47.89);
        for(int i=0;i<2;i++)
            pc.printf("%d\n",i);
        pc.printf("This line should always go with the first one\n");
    } // pc goes out of scope here, which is when it is written

    // or this way, but it all could have been one printf() anyway...
    PrintContext().printf("one line\n").printf("and another\n");

    return 0;
}

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: