Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does QCOMPARE(QString("1"), "1") cause a linker error?

I'm exploring Qt's unit test framework, and I noticed an odd thing - considering that QString already implements the equality operator for const char *, I would have expected QCOMPARE(QString("1"), "1") to just work, but instead it causes a linker error:

tst_untitled14test.obj:-1: error: LNK2019: unresolved external symbol "bool __cdecl QTest::qCompare<class QString,char const [2]>(class QString const &,char const (&)[2],char const *,char const *,char const *,int)" (??$qCompare@VQString@@$$BY01$$CBD@QTest@@YA_NABVQString@@AAY01$$CBDPBD22H@Z) referenced in function "private: void __thiscall Untitled14Test::testCase1(void)" (?testCase1@Untitled14Test@@AAEXXZ)

Example code:

QVERIFY(QString("1") == "1");         // This works.
QCOMPARE(QString("1"), QString("1")); // This works.
// QCOMPARE(QString("1"), "1");       // Causes a linker error!

Why is that? Doesn't QCOMPARE use the equality operator of the 2 terms?

Edit: Since it was asked in the comments, the project is created by Qt Creator's unit test wizard (File->New Project->Other Project->Qt Unit Test), so of course it has been set up properly, and QT += testlib is included.

like image 751
sashoalm Avatar asked Mar 17 '15 14:03

sashoalm


1 Answers

From Qt documentation

QCOMPARE is very strict on the data types. Both actual and expected have to be of the same type, otherwise the test won't compile. This prohibits unspecified behavior from being introduced; that is behavior that usually occurs when the compiler implicitly casts the argument.

In source code QCOMPARE looks like

#define QCOMPARE(actual, expected) \
do {\
    if (!QTest::qCompare(actual, expected, #actual, #expected, __FILE__, __LINE__))\
        return;\
} while (0)

template <typename T>
inline bool qCompare(T const &t1, T const &t2, const char *actual, const char *expected,
                        const char *file, int line)
{
    return compare_helper(t1 == t2, "Compared values are not the same",
                              toString(t1), toString(t2), actual, expected, file, line);
}

It is a template which requires first and second argument to be of the same type.

like image 100
Meefte Avatar answered Nov 10 '22 12:11

Meefte