Есть ли стандартное решение для буферизации выходных операций в C++?

Я написал этот простой класс, который обеспечивает буферизацию для общей операции вывода:

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_;
};

(Проверка ошибок опущена для простоты.) Следующий пример программы:

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;
}

затем генерирует следующий вывод:

Буфер записи размером 5: 0, 1, 2, 3, 4,
Буфер записи размером 5: 5, 6, 7, 8, 9,
Буфер записи размером 5: 10, 11, 12, 13, 14,
Буфер записи размером 3: 15, 16, 17,

Есть ли стандартное / лучшее решение этой проблемы, например, какой-нибудь контейнер STL / класс BOOST с аналогичными возможностями? Спасибо!

Дополнительный вопрос: вы бы предпочли использовать объект функции вместо ссылки на функцию flush_t?

РЕДАКТИРОВАТЬ

Я хотел бы использовать такую ​​буферизацию для любого типа T и любой flush операция, предоставляемая клиентом (не только символы и выходные потоки). Например:

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

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

записать данные в набор данных HDF5. (Здесь не решаются типы данных HDF5.)

2 ответа

Решение

Стандартным решением является подкласс std::streambuf, который был специально разработан для вашей задачи. Существует некоторая boost магия для облегчения реализации.

cout является буферизованным выводом по умолчанию. Ваше использование endl заставляет буфер сбрасывать вывод, но вы можете использовать "\n" intead. Если ваша программа требует использования либо флага unitbuf, либо манипуляторов flush или endl и вы хотите избежать очистки буфера, вы можете использовать специальный потоковый буфер, который не использует sync() для очистки потокового буфера, но у меня никогда не было необходимости, так что я неясен в деталях реализации.

Другие вопросы по тегам