Search code examples
c++buffering

Is there any standard solution for buffering output operations in C++?


I wrote this simple class that provides buffering for general output operation:

template <typename T>
class WriteBuffer {
        typedef void (&flush_t)(const T* values, const size_t size);

    public:
        WriteBuffer(size_t size, flush_t flush) : flush_(flush) {
            v_.reserve(size);
        }

       ~WriteBuffer() { flush(); }

        void flush() {
            if (v_.size() > 0) {
                flush_(&v_[0], v_.size());
                v_.clear();
            }
        }

        void write(const T value) {
            if (v_.size() == v_.capacity())
                flush();
            v_.push_back(value);
        }

    private:
        vector<T> v_;
        flush_t flush_;
};

(Error checking is omitted for simplicity.) The following example program:

void writeInt(const int* values, const size_t size) {
    cout << "Writing buffer of size " << size << ": " << endl;
    for (size_t i = 0; i < size; ++i)
        cout << values[i] << ", ";
    cout << endl;
}

int main(int argc, char* argv[]) {
    WriteBuffer<int> buffer(5, writeInt);

    for (size_t i = 0; i < 18; ++i)
        buffer.write(i);

    return 0;
}

then generates the following output:

Writing buffer of size 5: 0, 1, 2, 3, 4,
Writing buffer of size 5: 5, 6, 7, 8, 9,
Writing buffer of size 5: 10, 11, 12, 13, 14,
Writing buffer of size 3: 15, 16, 17,

Is there any standard/better solution of this problem, e.g. some STL container / BOOST class with similar capabilities? Thanks!

Additional question: Would you prefer using function object instead of function reference flush_t?

EDIT

I would like to use such buffering for any type T and any flush operation provided by the client (not only characters and output streams). For example:

template <typename T>
void write(const T* values, const size_t size) {
    ...
    H5Dwrite(..., values);
    ...
}

WriteBuffer<unsigned long> buffer(8192, write<unsigned long>);

to write data into HDF5 dataset. (Not solving here HDF5 data types.)


Solution

  • The standard solution is to subclass std::streambuf, which was exactly designed for your task. There is some boost magic to ease implementation.