Debao's Blog...

"left shift operator overloading for QDebug()"

Consider that we have create a custom type:

struct Point
Point(int x, int y):x(x),y(y){}
int x;
int y;

If we want to make it work with qDebug(), we need to implement a streaming operator:

QDebug operator<<(QDebug dbg, const Point &p)

But, wait ...

When we using pure c++, what we do is:

ostream &operator<<(ostream &out, const Point &p)

Why QDebug object is passed by value instead of reference?

qDebug() vs. std::cout

In first glance, qDebug() is very similiar to std::cout.

qDebug()<<"From Qt qDebug()";
std::cout<<"From C++ std::cout"<<std::endl;

However, each time we call qDebug(), a new QDebug object will be created.

QDebug qDebug() { return QDebug(QtDebugMsg); }

while std::cout is a global std::ostream object, the header file iostream is more or less like this:

namespace std
    extern ostream cout;
    static ios_base::Init __ioinit;

Why reference doesn't work for QDebug

We know that,

qDebug() << Point(1,2);

can be wrriten as:

QDebug(QtDebugMsg) << Point(1,2);

Which can also be wrriten as:

operator <<(QDebug(QtDebugMsg), Point(1,2));

As we can see, a temporary QDebug object is passed to the function in above statements.

But in C++, we know that,

A temporary cannot be bound to a non-const reference.

That why

QDebug operator<<(QDebug dbg, const Point &p)

should be used instead of

QDebug & operator<<(QDebug &dbg, const Point &p)


Some one complain that, though

QDebug & operator<<(QDebug &dbg, const Point &p)

doesn't work for qDebug()<<Point(1,2);, but it indeed works for qDebug()<<""<<Point(1,2);. Why?

The latter statement can be re-written as

operator <<(QDebug(QtDebugMsg).operator <<(""), Point(1,2));

and note that, QDebug has provided the member function for type char *:

QDebug & QDebug::operator<<(const char * s);

in which a reference to current QDebug object is return.

So C++ compiler will be happy with this now.