> ## Content Index
> Fetch the complete content index at: https://www.smallstepsystems.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Printing Custom Qt Types with qDebug()
- URL: https://www.smallstepsystems.com/printing-custom-qt-types-with-qdebug/
- Published: 2019-07-28T12:33:23.000Z
- Updated: 2026-01-25T13:44:26.000Z
- Author: Burkhard Stubert

When you define your own C++ types for a Qt application, you want to print their values with `qDebug()`,` qWarning()` or `qCritical()` eventually.

```
auto frame1 = QCanBusFrame{0x18ef0201U, QByteArray::fromHex("018A010000000000")};
qDebug() << "frame1 =" << frame1;
```

The C++ compiler will complain with this error message:

```
error: no match for ‘operator<<’ (operand types are ‘QDebug’ and ‘QCanBusFrame’)
```

The error message tells you to write your own output operator for the `QDebug` stream and for `QCanBusFrame`.

A custom C++ type that wants to play nicely with Qt should always define a `QDebug` output operator. Even the developers of the Qt library seem to forget it sometimes, as the example of `QCanBusFrame` shows.

The documentation of [QDebug Class](https://doc.qt.io/qt-5/qdebug.html?ref=smallstepsystems.com) gives some hints about writing custom types to `QDebug` streams and links to the sections [Providing Support for the qDebug() Stream Operator](https://doc.qt.io/qt-5/debug.html?ref=smallstepsystems.com#providing-support-for-the-qdebug-stream-operator) and [Making the Type Printable](https://doc.qt.io/qt-5/custom-types.html?ref=smallstepsystems.com#making-the-type-printable). The first implementation of the stream operator for `QCanBusFrame` is a simple adaptation of the example given in the documentation of [QDebug Class](https://doc.qt.io/qt-5/qdebug.html?ref=smallstepsystems.com).

```
QDebug operator<<(QDebug debug, const QCanBusFrame &frame)
{
    QDebugStateSaver saver(debug);
    debug.nospace() << frame.toString();
    return debug;
}
```

The line

```
qDebug() << "frame1 =" << frame1;
```

prints

```
frame1 = "18EF0201   [8]  01 8A 01 00 00 00 00 00"
```

The line `QDebugStateSaver saver(debug);` saves the current state of the stream and restores this state when exiting the operator function. Hence, formatting changes by the custom operator don't affect any other calls of `operator<<`. They stay local to the custom operator.

The `QDebug` stream has a special thing with spaces and with quotes. It inserts a space between each argument and encloses `QString`, `QByteArray` and `QChar` arguments with double quotes. With the inserted space replaced by "@", the last output looks as follows:

```
frame1 =@"18EF0201   [8]  01 8A 01 00 00 00 00 00"
```

As `"frame1 ="` has the type `const char *`, it is printed without quotes. The CAN frame, however, is enclosed with quotes, because `frame.toString()` has the type `QString`.

The formatting option `debug.nospace()` ensures that the stream operator for QCanBusFrames does not insert its own space between the equality sign and the opening quote. If you wrote

```
    debug.space() << frame.toString();
```

in the custom operator, the output (again with "@" instead of space) would be

```
frame1 =@@"18EF0201   [8]  01 8A 01 00 00 00 00 00"
```

If you wrote

```
debug.maybeSpace() << frame.toString();
```

the custom operator would insert a space or not depending on the preceding formatting options in the `QDebug` stream.

```
qDebug() << "frame1 =" << frame1;
# frame1 =@@"18EF0201   [8]  01 8A 01 00 00 00 00 00"

qDebug().nospace() << "frame1 =" << frame1;
# frame1 ="18EF0201   [8]  01 8A 01 00 00 00 00 00"

```

`qDebug().nospace()` disables the automatic insertion of spaces and prevents `debug.maybeSpace()` from inserting a space. By default, the insertion of spaces is enabled and `debug.maybeSpace()` inserts a space.

The output format of `QCanBusFrame::toString()` isn't ideal, because you cannot pass it to Linux CAN utilities like `[cansend](http://manpages.ubuntu.com/manpages/bionic/man1/cansend.1.html?ref=smallstepsystems.com)` and `[cangen](http://manpages.ubuntu.com/manpages/bionic/man1/cangen.1.html?ref=smallstepsystems.com)`. For example,

```
$ cansend can0 18EF0201#018A010000000000
```

writes `frame1` to the CAN interface `can0` from the Linux command line. The following implementation of `operator<<` produces the desired output format.

```
QDebug operator<<(QDebug debug, const QCanBusFrame &frame)
{
    QDebugStateSaver saver(debug);
    debug.nospace().noquote() 
        << QByteArray::number(frame.frameId(), 16) << "#"
        << frame.payload().toHex();
    return debug;
}
```

The option `noquote()` is required to suppress the quotes around the first and third argument, which are both `QByteArray`s.

The other message loggers `qInfo()`, `qWarning()`, `qCritical()` and `qFatal()` work with the custom type `QCanBusFrame` as well, because they all write to the `QDebug` stream.