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) {
开发者_C百科 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.)
The standard solution is to subclass std::streambuf
, which was exactly designed for your task. There is some boost
magic to ease implementation.
cout is by default buffered output. Your use of endl forces the buffer to flush it's output, but you can use "\n" intead. If you're program requires the use of either the flag unitbuf, or the manipulators flush or endl and you want to avoid flushing the buffer, you can supposedly use a special stream buffer that does not use sync() to flush the stream buffer, but I've never had a need to, so I'm unclear on the implementation details.
精彩评论