Using << operator to write to both a file and cout

前端 未结 6 1104
滥情空心
滥情空心 2020-12-02 01:10

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

6条回答
  •  误落风尘
    2020-12-02 01:10

    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.

提交回复
热议问题