Есть ли стандартное решение для буферизации выходных операций в C ++? - PullRequest
2 голосов
/ 17 февраля 2011

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

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

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

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,

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

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

EDIT

Я хотел бы использовать такую ​​буферизацию для любого типа 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 ]

3 голосов
/ 17 февраля 2011

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

1 голос
/ 17 февраля 2011

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

...