I\'d like to overload << operator to write the value it takes to a file and cout. I have tried to do it with following code, but couldn\'t succeed it. It just writes t
To implement a full stream interface you should build a stream buffer and a stream:
#include
#include
#include
#include
// BasicMultiStreamBuffer
// ============================================================================
template, class Allocator = std::allocator >
class BasicMultiStreamBuffer : public std::basic_stringbuf
{
// Types
// =====
private:
typedef typename std::basic_stringbuf Base;
public:
typedef typename std::basic_streambuf buffer_type;
typedef typename buffer_type::char_type char_type;
typedef typename buffer_type::traits_type traits_type;
typedef typename buffer_type::int_type int_type;
typedef typename buffer_type::pos_type pos_type;
typedef typename buffer_type::off_type off_type;
private:
typedef typename std::vector container_type;
public:
typedef typename container_type::size_type size_type;
typedef typename container_type::value_type value_type;
typedef typename container_type::reference reference;
typedef typename container_type::const_reference const_reference;
typedef typename container_type::iterator iterator;
typedef typename container_type::const_iterator const_iterator;
// Construction/Destructiion
// =========================
public:
BasicMultiStreamBuffer()
{}
BasicMultiStreamBuffer(buffer_type* a) {
if(a) {
m_buffers.reserve(1);
m_buffers.push_back(a);
}
}
template
BasicMultiStreamBuffer(Iterator first, Iterator last)
: m_buffers(first, last)
{}
~BasicMultiStreamBuffer() {
sync();
}
private:
BasicMultiStreamBuffer(BasicMultiStreamBuffer const&); // No Copy.
BasicMultiStreamBuffer& operator=(BasicMultiStreamBuffer const&); // No Copy.
// Capacity
// ========
public:
bool empty() const { return m_buffers.empty(); }
size_type size() const { return m_buffers.size(); }
// Iterator
// ========
public:
iterator begin() { return m_buffers.begin(); }
const_iterator begin() const { return m_buffers.end(); }
iterator end() { return m_buffers.end(); }
const_iterator end() const { return m_buffers.end(); }
// Modifiers
// =========
public:
void insert(buffer_type* buffer) {
if(buffer) m_buffers.push_back(buffer);
}
void erase(buffer_type* buffer) {
iterator pos = this->begin();
for( ; pos != this->end(); ++pos) {
if(*pos == buffer) {
m_buffers.erase(pos);
break;
}
}
}
// Synchronization
// ===============
protected:
virtual int sync() {
int result = 0;
if( ! m_buffers.empty()) {
char_type* p = this->pbase();
std::streamsize n = this->pptr() - p;
if(n) {
const_iterator pos = m_buffers.begin();
for( ; pos != m_buffers.end(); ++pos) {
std::streamoff offset = 0;
while(offset < n) {
int k = (*pos)->sputn(p + offset, n - offset);
if(0 <= k) offset += k;
else {
result = -1;
break;
}
}
if((*pos)->pubsync() == -1) result = -1;
}
this->setp(this->pbase(), this->epptr());
}
}
if(Base::sync() == -1) result = -1;
return result;
}
private:
container_type m_buffers;
};
typedef BasicMultiStreamBuffer OStreamBuffers;
// BasicMultiStream
// ============================================================================
template, class Allocator = std::allocator >
class BasicMultiStream : public std::basic_ostream
{
// Types
// =====
private:
typedef std::basic_ostream Base;
public:
typedef BasicMultiStreamBuffer multi_buffer;
typedef std::basic_ostream stream_type;
typedef typename multi_buffer::buffer_type buffer_type;
typedef typename multi_buffer::char_type char_type;
typedef typename multi_buffer::traits_type traits_type;
typedef typename multi_buffer::int_type int_type;
typedef typename multi_buffer::pos_type pos_type;
typedef typename multi_buffer::off_type off_type;
typedef typename multi_buffer::size_type size_type;
typedef typename multi_buffer::value_type value_type;
typedef typename multi_buffer::reference reference;
typedef typename multi_buffer::const_reference const_reference;
typedef typename multi_buffer::iterator iterator;
typedef typename multi_buffer::const_iterator const_iterator;
// Construction
// ============
public:
BasicMultiStream()
: Base(&m_buffer)
{}
BasicMultiStream(stream_type& stream)
: Base(&m_buffer), m_buffer(stream.rdbuf())
{}
template
BasicMultiStream(StreamIterator& first, StreamIterator& last)
: Base(&m_buffer)
{
while(first != last) insert(*first++);
}
private:
BasicMultiStream(const BasicMultiStream&); // No copy.
const BasicMultiStream& operator = (const BasicMultiStream&); // No copy.
// Capacity
// ========
public:
bool empty() const { return m_buffer.empty(); }
size_type size() const { return m_buffer.size(); }
// Iterator
// ========
public:
iterator begin() { return m_buffer.begin(); }
const_iterator begin() const { return m_buffer.end(); }
iterator end() { return m_buffer.end(); }
const_iterator end() const { return m_buffer.end(); }
// Modifiers
// =========
public:
void insert(stream_type& stream) { m_buffer.insert(stream.rdbuf()); }
void erase(stream_type& stream) { m_buffer.erase(stream.rdbuf()); }
private:
multi_buffer m_buffer;
};
typedef BasicMultiStream MultiStream;
// Test
// =============================================================================
#include
int main() {
MultiStream out;
out.insert(std::cout);
out.insert(std::clog);
out << "Hello\n";
}
Here, the output is buffered in a string stream buffer and synchronized to the destination streams.