Using << operator to write to file and cout

I would like to overload the <<<statement to write the value that is required for the file and cout. I tried to do this with the following code, but could not succeed. It simply writes the value to a text file. Any help would be greatly appreciated. Thank.

void operator<<(std::ostream& os, const string& str)
{
    std::cout << str;
    os << str;
}

int main() {
    ofstream fl;
    fl.open("test.txt");
    fl << "!!!Hello World!!!" << endl;
    return 0;
}
+4
source share
6 answers

Create a helper class and overload statements that take care of two-stream streaming. Use a helper class instead of trying to override the standard library implementations of overloaded functions operator<<.

:

#include <iostream>
#include <fstream>

struct MyStreamingHelper
{
    MyStreamingHelper(std::ostream& out1,
                      std::ostream& out2) : out1_(out1), out2_(out2) {}
    std::ostream& out1_;
    std::ostream& out2_;
};

template <typename T>
MyStreamingHelper& operator<<(MyStreamingHelper& h, T const& t)
{
   h.out1_ << t;
   h.out2_ << t;
   return h;
}

MyStreamingHelper& operator<<(MyStreamingHelper& h, std::ostream&(*f)(std::ostream&))
{
   h.out1_ << f;
   h.out2_ << f;
   return h;
}

int main()
{
   std::ofstream fl;
   fl.open("test.txt");
   MyStreamingHelper h(fl, std::cout);
   h << "!!!Hello World!!!" << std::endl;
   return 0;
}
+8

, :

#include <ostream>
#include <sstream>
#include <streambuf>
#include <vector>

// BasicMultiStreamBuffer
// ============================================================================

template<class Char, class Traits = std::char_traits<Char>, class Allocator = std::allocator<Char> >
class BasicMultiStreamBuffer : public std::basic_stringbuf<Char, Traits, Allocator>
{
    // Types
    // =====

    private:
    typedef typename std::basic_stringbuf<Char, Traits> Base;

    public:
    typedef typename std::basic_streambuf<Char, Traits> 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<buffer_type*> 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 <typename Iterator>
    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<char> OStreamBuffers;


// BasicMultiStream
// ============================================================================

template<class Char, class Traits = std::char_traits<Char>, class Allocator = std::allocator<Char> >
class BasicMultiStream : public std::basic_ostream<Char, Traits>
{
    // Types
    // =====

    private:
    typedef std::basic_ostream<Char, Traits> Base;

    public:
    typedef BasicMultiStreamBuffer<Char, Traits, Allocator> multi_buffer;
    typedef std::basic_ostream<Char, Traits> 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 <typename StreamIterator>
    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<char> MultiStream;


// Test
// =============================================================================

#include <iostream>
int main() {
    MultiStream out;
    out.insert(std::cout);
    out.insert(std::clog);
    out << "Hello\n";
}

.

+2

, , std::ostream& const std::string&. :

fl << "!!!Hello World!!!" << endl;

, . std::string, char const*. , , , char const* const std::string&, .

, , - , std, :

namespace std { // Simplification:
    std::ostream& operator<<(std::ostream& os, char const* str);
}

, . , , - - ADL . (, std) - , ADL, , , , . :

std::operator<<(f1, "!!!Hello World!!!") << std::endl;

std::getline(). , using namespace std using std::getline:

getline(std::cin, line);

std::cin , std::getline(), std:: .

, , . , std::string :

fl << std::string("!!!Hello World!!!") << endl;

, , std, , std. , .

  • std::ostream& void return os, << endl.

  • os << str. , os << str.c_str(), char const* std.

, .

+1

, , , boost .

#include <iostream>
#include <fstream>
#include <boost/iostreams/tee.hpp>
#include <boost/iostreams/stream.hpp>

typedef boost::iostreams::tee_device<std::ostream, std::ostream> teedev;
typedef boost::iostreams::stream<teedev, std::char_traits<typename std::ostream::char_type>, std::allocator< typename std::ostream::char_type > > tee_stream;

int main(int argc, char* argv[])
{
    std::ofstream of;
    of.open( "test.txt" );

    teedev td( of, std::cout );
    tee_stream ts(td);

    ts << "!!!Hello World!!!" << std::endl;

    return 0;
}
+1

, < .

< (ostream &), < str < ; .

< , , os < ; , fl < "";

0

- streambuf, streambuf. - :

class LoggingStreambuf : public std::streambuf
{
    std::streambuf* myPrinciple;
    std::ostream*   myOwner;
    std::filebuf    myLogging;
protected:
    int overflow( int ch ) override
    {
        myLogging->sputc( ch );
        return myPrinciple->sputc( ch );
    }
public:
    LoggingStreambuf( std::streambuf* principal, std::string const& logFileName )
        : myPrinciple( principal )
        , myOwner( nullptr )
        , myLogging( logFileName )
    {
    }

    LoggingStreambuf( std::ostream& principal, std::string const& logFileName )
        : myPrinciple( principal.rdbuf() )
        , myOwner( &principal )
        , myLogging( logFileName )
    {
        myOwner.rdbuf( this );
    }

    ~LoggingStreambuf()
    {
        if ( myOwner != nullptr ) {
            myOwner.rdbuf( myPrinciple );
        }
    }
};

( , - , , . , , std::streambuf* std::ostream streambuf.)

, :

LoggingStreambuf logger( std::cout, "logfile.txt" );
//  And output to std::cout as usual...

, : - , std::streambuf, , .

0

Source: https://habr.com/ru/post/1546017/


All Articles