Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does QDebug() << stuff; add a newline automatically?

Tags:

c++

stream

qt

I'm trying to implement my own qDebug() style debug-output stream, this is basically what I have so far:

struct debug
{
#if defined(DEBUG)
    template<typename T>
    std::ostream& operator<<(T const& a) const
    {
        std::cout << a;
        return std::cout;
    }
#else
    template<typename T>
    debug const& operator<<(T const&) const
    {
        return *this;
    }

    /* must handle manipulators (endl) separately:
     * manipulators are functions that take a stream& as argument and return a
     * stream&
     */
    debug const& operator<<(std::ostream& (*manip)(std::ostream&)) const
    {
        // do nothing with the manipulator
        return *this;
    }
#endif
};

Typical usage:

debug() << "stuff" << "more stuff" << std::endl;

But I'd like not to have to add std::endl;

My question is basically, how can I tell when the return type of operator<< isn't going to be used by another operator<< (and so append endl)?

The only way I can think of to achieve anything like this would be to create a list of things to print with associated with each temporary object created by qDebug(), then to print everything, along with trailing newline (and I could do clever things like inserting spaces) in ~debug(), but obviously this is not ideal since I don't have a guarantee that the temporary object is going to be destroyed until the end of the scope (or do I?).

like image 860
James Avatar asked Feb 01 '10 19:02

James


2 Answers

Something like this will do:

struct debug {
    debug() {
    }

    ~debug() {
        std::cerr << m_SS.str() << std::endl;
    }

public:
    // accepts just about anything
    template<class T>
    debug &operator<<(const T &x) {
        m_SS << x;
        return *this;
    }
private:
    std::ostringstream m_SS;
};

Which should let you do things like this:

debug() << "hello world";

I've used a pattern like this combined with a lock to provide a stream like logging system which can guarantee that log entries are written atomically.

NOTE: untested code, but should work :-)

like image 200
Evan Teran Avatar answered Oct 18 '22 15:10

Evan Teran


Qt uses a method similar to @Evan. See a version of qdebug.h for the implementation details, but they stream everything to an underlying text stream, and then flush the stream and an end-line on destruction of the temporary QDebug object returned by qDebug().

like image 29
Bill Avatar answered Oct 18 '22 14:10

Bill