Search code examples
c++qtqt5.5

Problems with new QFlags helpers for qDebug() in QT5.5


I have the following code

#include <QDebug>  //Needed for other stuff!!
#include <QDataStream>

class TestClass {
public:
    class SubClass {
    public:
        QString a;
        int b;

        /*
        //Needed for QDataStream but not relevant for the generated error
        friend QDataStream& operator<<(QDataStream& os, SubClass const& f)
        {
            os << f.a;
            os << f.b;
            return os;
        }

        friend QDataStream& operator>>(QDataStream& is, SubClass& f)
        {
            is >> f.a;
            is >> f.b;
            return is;
        }*/

        friend QDataStream& operator<< <SubClass>(QDataStream&, QList<SubClass> const&);
        friend QDataStream& operator>> <SubClass>(QDataStream&, QList<SubClass>&);

    };
};

Compiling it with qt5.5 gives me the following errors:

/usr/include/qt/QtCore/qflags.h:88: error: invalid application of 'sizeof' to an incomplete type 'TestClass::SubClass'
    Q_STATIC_ASSERT_X((sizeof(Enum) <= sizeof(int)),
                   ^~~~~~~~~~~~
/usr/include/qt/QtCore/qtypetraits.h:478: error: 'TestClass::SubClass' is an incomplete type
    : integral_constant<bool, (T(0) < T(-1))> {};
                               ^
/usr/include/qt/QtCore/qdebug.h:279: in instantiation of template class 'QtPrivate::IsQEnumHelper<QFlags<TestClass::SubClass> >' requested here
    QtPrivate::IsQEnumHelper<T>::Value || QtPrivate::IsQEnumHelper<QFlags<T> >::Value,
                                                     ^
main.cpp:25: while substituting explicitly-specified template arguments into function template 'operator<<'
        friend QDataStream& operator<< <SubClass>(QDataStream&, QList<SubClass> const&);
                            ^

The reason for that seems to lie in the following code of the QDebug header file (qdebug.h:277):

template <class T>
inline typename QtPrivate::QEnableIf<
    QtPrivate::IsQEnumHelper<T>::Value || QtPrivate::IsQEnumHelper<QFlags<T> >::Value,
    QDebug>::Type
operator<<(QDebug debug, const QFlags<T> &flags)
{
  //...
}

Compiling with qt5.4 works fine. The right template function is taken (qdatastream.h:241)

template <typename T>
QDataStream& operator<<(QDataStream& s, const QList<T>& l)
{
   //...
}

Questions:

  1. I would like to know why the template from qdebug.h is taken into consideration. I have some ideas, but an answer with the appropriate links to the c++ standard and a proper explanation would be nice.
  2. Is there a workaround for this or should I submit a bugreport to qt?

Solution

  • The following (simplified code) generates the same error.

    #include <QDebug>  //Needed to cause the error
    
    class TestClassA {};
    class TestClassB {};
    
    template <typename T>
    TestClassA& operator<<(TestClassA& s, T& l) {
        Q_UNUSED(l)
        return s;
    }
    
    template TestClassA& operator<< <TestClassB>(TestClassA& s, TestClassB& l);
    

    Bugreport opened at: https://bugreports.qt.io/browse/QTBUG-47375

    Update: They fixed it. The Fix will be included in Qt 5.5.1