Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

C++ structs equal operator: invalid operands to binary expression

Qt 5.15.5 msvc2019

compiler

clang version 12.0.0  
Target: x86_64-pc-windows-msvc  
struct FrameStyle
{
    QColor color; // has both == and != operators
    Qt::PenStyle penStyle; // enum
    Distance padding; // has == operator

    bool operator==(const FrameStyle& other)
    {
        return other.color == color
                && other.penStyle == penStyle
                && other.padding == padding;
    }
};

FrameStyle style;
FrameStyle m_prevStyle;


const bool styleChanged = !(style == m_prevStyle); // ok
const bool styleChanged = style != m_prevStyle; // Invalid operands to binary expression ('FrameStyle' and 'FrameStyle')
error: invalid operands to binary expression ('gns::FrameStyle' and 'gns::FrameStyle')
    const bool styleChanged = style != m_prevStyle;
                              ~~~~~ ^  ~~~~~~~~~~~
E:\5.15.8\msvc\include\QtCore/qchar.h(62,30): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'char' for 1st argument
Q_DECL_CONSTEXPR inline bool operator!=(char lhs, QLatin1Char rhs) noexcept { return lhs != rhs.toLatin1(); }
                             ^
E:\5.15.8\msvc\include\QtCore/qchar.h(69,30): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'QLatin1Char' for 1st argument
Q_DECL_CONSTEXPR inline bool operator!=(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() != rhs; }
                             ^
E:\5.15.8\msvc\include\QtCore/qchar.h(640,30): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'QChar' for 1st argument
Q_DECL_CONSTEXPR inline bool operator!=(QChar c1, QChar c2) noexcept { return !operator==(c1, c2); }
                             ^
E:\5.15.8\msvc\include\QtCore/qchar.h(651,30): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'QChar' for 1st argument
Q_DECL_CONSTEXPR inline bool operator!=(QChar lhs, std::nullptr_t) noexcept { return !operator==(lhs, nullptr); }
                             ^
E:\5.15.8\msvc\include\QtCore/qchar.h(656,30): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'std::nullptr_t' (aka 'nullptr_t') for 1st argument
Q_DECL_CONSTEXPR inline bool operator!=(std::nullptr_t, QChar rhs) noexcept { return !operator==(nullptr, rhs); }
                             ^
E:\5.15.8\msvc\include\QtCore/qbytearray.h(690,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QByteArray' for 1st argument
inline bool operator!=(const QByteArray &a1, const QByteArray &a2) noexcept
            ^
E:\5.15.8\msvc\include\QtCore/qbytearray.h(692,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QByteArray' for 1st argument
inline bool operator!=(const QByteArray &a1, const char *a2) noexcept
            ^
E:\5.15.8\msvc\include\QtCore/qbytearray.h(694,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const char *' for 1st argument
inline bool operator!=(const char *a1, const QByteArray &a2) noexcept
            ^
E:\5.15.8\msvc\include\QtCore/qbytearray.h(811,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QByteArray::FromBase64Result' for 1st argument
inline bool operator!=(const QByteArray::FromBase64Result &lhs, const QByteArray::FromBase64Result &rhs) noexcept
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1379,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'QString::Null' for 1st argument
inline bool operator!=(QString::Null, QString::Null) { return false; }
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1381,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'QString::Null' for 1st argument
inline bool operator!=(QString::Null, const QString &s) { return !s.isNull(); }
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1383,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QString' for 1st argument
inline bool operator!=(const QString &s, QString::Null) { return !s.isNull(); }
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1388,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'QLatin1String' for 1st argument
inline bool operator!=(QLatin1String s1, QLatin1String s2) noexcept
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1432,32): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const char *' for 1st argument
inline QT_ASCII_CAST_WARN bool operator!=(const char *s1, const QString &s2)
                               ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1445,32): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const char *' for 1st argument
inline QT_ASCII_CAST_WARN bool operator!=(const char *s1, QLatin1String s2)
                               ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1822,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QStringRef' for 1st argument
inline bool operator!=(const QStringRef &s1, const QStringRef &s2) noexcept
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1834,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QString' for 1st argument
inline bool operator!=(const QString &lhs, const QStringRef &rhs) noexcept { return lhs.compare(rhs) != 0; }
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1841,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QStringRef' for 1st argument
inline bool operator!=(const QStringRef &lhs, const QString &rhs) noexcept { return rhs != lhs; }
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1870,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'QLatin1String' for 1st argument
inline bool operator!=(QLatin1String lhs, const QStringRef &rhs) noexcept { return rhs.compare(lhs) != 0; }
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1877,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QStringRef' for 1st argument
inline bool operator!=(const QStringRef &lhs, QLatin1String rhs) noexcept { return rhs != lhs; }
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1891,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'QChar' for 1st argument
inline bool operator!=(QChar lhs, const QString &rhs) noexcept { return !(lhs == rhs); }
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1896,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QString' for 1st argument
inline bool operator!=(const QString &lhs, QChar rhs) noexcept { return !(rhs == lhs); }
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1910,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'QChar' for 1st argument
inline bool operator!=(QChar lhs, const QStringRef &rhs) noexcept { return !(lhs == rhs); }
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1915,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QStringRef' for 1st argument
inline bool operator!=(const QStringRef &lhs, QChar rhs) noexcept { return !(rhs == lhs); }
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1929,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'QChar' for 1st argument
inline bool operator!=(QChar lhs, QLatin1String rhs) noexcept { return !(lhs == rhs); }
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1934,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'QLatin1String' for 1st argument
inline bool operator!=(QLatin1String lhs, QChar rhs) noexcept { return !(rhs == lhs); }
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1942,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'QStringView' for 1st argument
inline bool operator!=(QStringView lhs, QStringView rhs) noexcept { return !(lhs == rhs); }
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1950,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'QStringView' for 1st argument
inline bool operator!=(QStringView lhs, QChar rhs) noexcept { return lhs != QStringView(&rhs, 1); }
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1957,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'QChar' for 1st argument
inline bool operator!=(QChar lhs, QStringView rhs) noexcept { return QStringView(&lhs, 1) != rhs; }
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1965,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'QStringView' for 1st argument
inline bool operator!=(QStringView lhs, QLatin1String rhs) noexcept { return !(lhs == rhs); }
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1972,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'QLatin1String' for 1st argument
inline bool operator!=(QLatin1String lhs, QStringView rhs) noexcept { return !(lhs == rhs); }
            ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1981,32): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QStringRef' for 1st argument
inline QT_ASCII_CAST_WARN bool operator!=(const QStringRef &lhs, const QByteArray &rhs) { return lhs.compare(rhs) != 0; }
                               ^
E:\5.15.8\msvc\include\QtCore/qstring.h(1988,32): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QByteArray' for 1st argument
inline QT_ASCII_CAST_WARN bool operator!=(const QByteArray &lhs, const QStringRef &rhs) { return rhs.compare(lhs) != 0; }
                               ^
E:\5.15.8\msvc\include\QtCore/qstring.h(2010,32): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const char *' for 1st argument
inline QT_ASCII_CAST_WARN bool operator!=(const char *s1, const QStringRef &s2)
                               ^
E:\5.15.8\msvc\include\QtCore/qpoint.h(168,30): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QPoint' for 1st argument
Q_DECL_CONSTEXPR inline bool operator!=(const QPoint &p1, const QPoint &p2)
                             ^
E:\5.15.8\msvc\include\QtCore/qpoint.h(363,30): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QPointF' for 1st argument
Q_DECL_CONSTEXPR inline bool operator!=(const QPointF &p1, const QPointF &p2)
                             ^
E:\5.15.8\msvc\include\QtCore/qvariant.h(616,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QVariant' for 1st argument
inline bool operator!=(const QVariant &v1, const QVariantComparisonHelper &v2)
            ^
E:\5.15.8\msvc\include\QtCore/qmetaobject.h(202,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QMetaMethod' for 1st argument
inline bool operator!=(const QMetaMethod &m1, const QMetaMethod &m2)
            ^
E:\5.15.8\msvc\include\QtCore/qmargins.h(144,30): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QMargins' for 1st argument
Q_DECL_CONSTEXPR inline bool operator!=(const QMargins &m1, const QMargins &m2) noexcept
                             ^
E:\5.15.8\msvc\include\QtCore/qmargins.h(380,30): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QMarginsF' for 1st argument
Q_DECL_CONSTEXPR inline bool operator!=(const QMarginsF &lhs, const QMarginsF &rhs) noexcept
                             ^
E:\5.15.8\msvc\include\QtCore/qsize.h(178,30): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QSize' for 1st argument
Q_DECL_CONSTEXPR inline bool operator!=(const QSize &s1, const QSize &s2) noexcept
                             ^
E:\5.15.8\msvc\include\QtCore/qsize.h(353,30): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QSizeF' for 1st argument
Q_DECL_CONSTEXPR inline bool operator!=(const QSizeF &s1, const QSizeF &s2) noexcept
                             ^
E:\5.15.8\msvc\include\QtCore/qrect.h(459,30): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QRect' for 1st argument
Q_DECL_CONSTEXPR inline bool operator!=(const QRect &r1, const QRect &r2) noexcept
                             ^
E:\5.15.8\msvc\include\QtCore/qrect.h(866,30): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QRectF' for 1st argument
Q_DECL_CONSTEXPR inline bool operator!=(const QRectF &r1, const QRectF &r2) noexcept
                             ^
E:\5.15.8\msvc\include\QtGui/qvector2d.h(216,30): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QVector2D' for 1st argument
Q_DECL_CONSTEXPR inline bool operator!=(const QVector2D &v1, const QVector2D &v2)
                             ^
E:\5.15.8\msvc\include\QtGui/qevent.h(877,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'QPointingDeviceUniqueId' for 1st argument
inline bool operator!=(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) noexcept
            ^
C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\shared/guiddef.h(197,15): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const GUID' (aka 'const _GUID') for 1st argument
__inline bool operator!=(REFGUID guidOne, REFGUID guidOther)
              ^
E:\5.15.8\msvc\include\QtGui/qvector3d.h(241,30): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QVector3D' for 1st argument
Q_DECL_CONSTEXPR inline bool operator!=(const QVector3D &v1, const QVector3D &v2)
                             ^
E:\5.15.8\msvc\include\QtGui/qvector4d.h(241,30): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QVector4D' for 1st argument
Q_DECL_CONSTEXPR inline bool operator!=(const QVector4D &v1, const QVector4D &v2)
                             ^
E:\5.15.8\msvc\include\QtGui/qquaternion.h(289,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QQuaternion' for 1st argument
inline bool operator!=(const QQuaternion &q1, const QQuaternion &q2)
            ^
E:\5.15.8\msvc\include\QtGui/qsurfaceformat.h(173,19): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QSurfaceFormat' for 1st argument
Q_GUI_EXPORT bool operator!=(const QSurfaceFormat&, const QSurfaceFormat&);
                  ^
E:\5.15.8\msvc\include\QtGui/qcursor.h(130,13): note: candidate function not viable: no known conversion from 'gns::FrameStyle' to 'const QCursor' for 1st argument
inline bool operator!=(const QCursor &lhs, const QCursor &rhs) noexcept { return !(lhs == rhs); }
            ^
E:\5.15.8\msvc\include\QtCore/qpair.h(118,41): note: candidate template ignored: could not match 'QPair<type-parameter-0-0, type-parameter-0-1>' against 'gns::FrameStyle'
Q_DECL_CONSTEXPR Q_INLINE_TEMPLATE bool operator!=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2)
                                        ^
E:\5.15.8\msvc\include\QtCore/qscopedpointer.h(190,13): note: candidate template ignored: could not match 'QScopedPointer<type-parameter-0-0, type-parameter-0-1>' against 'gns::FrameStyle'
inline bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs) noexcept
            ^
E:\5.15.8\msvc\include\QtCore/qscopedpointer.h(208,13): note: candidate template ignored: could not match 'QScopedPointer<type-parameter-0-0, type-parameter-0-1>' against 'gns::FrameStyle'
inline bool operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t) noexcept
            ^
E:\5.15.8\msvc\include\QtCore/qscopedpointer.h(214,13): note: candidate template ignored: could not match 'QScopedPointer<type-parameter-0-0, type-parameter-0-1>' against 'gns::FrameStyle'
inline bool operator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs) noexcept
            ^
E:\5.15.8\msvc\include\QtCore/qvarlengtharray.h(573,6): note: candidate template ignored: could not match 'QVarLengthArray<type-parameter-0-0, Prealloc>' against 'gns::FrameStyle'
bool operator!=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
     ^
E:\5.15.8\msvc\include\QtCore/qsharedpointer_impl.h(752,6): note: candidate template ignored: could not match 'QSharedPointer<type-parameter-0-0>' against 'gns::FrameStyle'
bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) noexcept
     ^
E:\5.15.8\msvc\include\QtCore/qsharedpointer_impl.h(768,6): note: candidate template ignored: could not match 'QSharedPointer<type-parameter-0-0>' against 'gns::FrameStyle'
bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2) noexcept
     ^
E:\5.15.8\msvc\include\QtCore/qsharedpointer_impl.h(773,6): note: candidate template ignored: could not match 'const T *' against 'gns::FrameStyle'
bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2) noexcept
     ^
E:\5.15.8\msvc\include\QtCore/qsharedpointer_impl.h(784,6): note: candidate template ignored: could not match 'QSharedPointer<type-parameter-0-0>' against 'gns::FrameStyle'
bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) noexcept
     ^
E:\5.15.8\msvc\include\QtCore/qsharedpointer_impl.h(796,13): note: candidate template ignored: could not match 'QSharedPointer<type-parameter-0-0>' against 'gns::FrameStyle'
inline bool operator!=(const QSharedPointer<T> &lhs, std::nullptr_t) noexcept
            ^
E:\5.15.8\msvc\include\QtCore/qsharedpointer_impl.h(808,13): note: candidate template ignored: could not match 'QSharedPointer<type-parameter-0-0>' against 'gns::FrameStyle'
inline bool operator!=(std::nullptr_t, const QSharedPointer<T> &rhs) noexcept
            ^
E:\5.15.8\msvc\include\QtCore/qsharedpointer_impl.h(820,13): note: candidate template ignored: could not match 'QWeakPointer<type-parameter-0-0>' against 'gns::FrameStyle'
inline bool operator!=(const QWeakPointer<T> &lhs, std::nullptr_t) noexcept
            ^
E:\5.15.8\msvc\include\QtCore/qsharedpointer_impl.h(832,13): note: candidate template ignored: could not match 'QWeakPointer<type-parameter-0-0>' against 'gns::FrameStyle'
inline bool operator!=(std::nullptr_t, const QWeakPointer<T> &rhs) noexcept
            ^
E:\5.15.8\msvc\include\QtCore/qpointer.h(114,13): note: candidate template ignored: could not match 'const T *' against 'gns::FrameStyle'
inline bool operator!=(const T *o, const QPointer<T> &p)
            ^
E:\5.15.8\msvc\include\QtCore/qpointer.h(118,13): note: candidate template ignored: could not match 'QPointer<type-parameter-0-0>' against 'gns::FrameStyle'
inline bool operator!= (const QPointer<T> &p, const T *o)
            ^
E:\5.15.8\msvc\include\QtCore/qpointer.h(122,13): note: candidate template ignored: could not match 'T *' against 'gns::FrameStyle'
inline bool operator!=(T *o, const QPointer<T> &p)
            ^
E:\5.15.8\msvc\include\QtCore/qpointer.h(126,13): note: candidate template ignored: could not match 'QPointer<type-parameter-0-0>' against 'gns::FrameStyle'
inline bool operator!= (const QPointer<T> &p, T *o)
            ^
E:\5.15.8\msvc\include\QtCore/qpointer.h(130,13): note: candidate template ignored: could not match 'QPointer<type-parameter-0-0>' against 'gns::FrameStyle'
inline bool operator!= (const QPointer<T> &p1, const QPointer<T> &p2)
            ^
1 error generated.

Why do I ever have to overload the equal operator in this case?
Why don’t I get automatic not equal operator?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

This is how C++ used to be since its inception… until C++20, in which default comparisons were introduced, https://en.cppreference.com/w/cpp/language/default_comparisons.

    bool operator==(const FrameStyle& other) = default;  // c++20

(this will provide a consistent operator!= as I understand)

It has an interesting backstory involving Dennis Ritchie (from C), Stroustrup, and Stepanov.
Some people were worried that an element by element equality would mean the incorrect thing for structures where data is indirected (e.g. the pointer member in a dynamic array).
The counterargument was that this was inconsistent with operator=, which is generally provided by default, even if it means the incorrect thing.

I agree with the opinion that operator= and operator== (and operator!=) should be provided default and it is the developer responsibility to change its meaning when necessary.

Having said that, in your case, I see two problems:

  • Make the method const, bool operator==(const FrameStyle& other) const
  • Make it a friend function. This will save some headaches.
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading