diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2015-11-10 12:41:37 +0100 |
---|---|---|
committer | Marc Mutz <marc.mutz@kdab.com> | 2015-11-22 12:26:20 +0000 |
commit | 5660ce600422e734aa40086efd58c1ab7815eb3e (patch) | |
tree | e6374f1cccd19ac6e18e746f4e9947b38b56e7c0 /tests/auto/other | |
parent | ecb6835a9fa0501cefcb1ab7f02e5bb7736afcd4 (diff) |
tst_compiler: check more cases for RVALUE_REFS
Check that we can use std::forward, and that the compiler
synthesizes move special member functions when it should.
MSVC only supports the latter since the Nov 2013 CTP,
which, for our intents and purposes, means VC2015.
Change-Id: I8d8e4ae064abce90076a05b3b637950ab7d21dac
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
Diffstat (limited to 'tests/auto/other')
-rw-r--r-- | tests/auto/other/compiler/tst_compiler.cpp | 86 |
1 files changed, 75 insertions, 11 deletions
diff --git a/tests/auto/other/compiler/tst_compiler.cpp b/tests/auto/other/compiler/tst_compiler.cpp index 981206cc9e..af0fa4682d 100644 --- a/tests/auto/other/compiler/tst_compiler.cpp +++ b/tests/auto/other/compiler/tst_compiler.cpp @@ -1128,24 +1128,88 @@ void tst_Compiler::cxx11_ref_qualifiers() #endif } +class MoveDefinedQString { + QString s; +public: + MoveDefinedQString() : s() {} + explicit MoveDefinedQString(const QString &s) : s(s) {} + MoveDefinedQString(const MoveDefinedQString &other) : s(other.s) {} +#ifdef Q_COMPILER_RVALUE_REFS + MoveDefinedQString(MoveDefinedQString &&other) : s(std::move(other.s)) { other.s.clear(); } + MoveDefinedQString &operator=(MoveDefinedQString &&other) + { s = std::move(other.s); other.s.clear(); return *this; } +#endif + MoveDefinedQString &operator=(const MoveDefinedQString &other) { s = other.s; return *this; } + +private: + friend bool operator==(const MoveDefinedQString &lhs, const MoveDefinedQString &rhs) + { return lhs.s == rhs.s; } + friend bool operator!=(const MoveDefinedQString &lhs, const MoveDefinedQString &rhs) + { return !operator==(lhs, rhs); } + friend char* toString(const MoveDefinedQString &mds) + { using namespace QTest; return toString(mds.s); } +}; + void tst_Compiler::cxx11_rvalue_refs() { #ifndef Q_COMPILER_RVALUE_REFS QSKIP("Compiler does not support C++11 feature"); #else - int i = 1; - i = std::move(i); - - QString s = "Hello"; - QString t = std::move(s); - QCOMPARE(t, QString("Hello")); + // we require std::move: + { + int i = 1; + i = std::move(i); + + MoveDefinedQString s("Hello"); + MoveDefinedQString t = std::move(s); + QCOMPARE(t, MoveDefinedQString("Hello")); + QCOMPARE(s, MoveDefinedQString()); + + s = t; + t = std::move(s); + QCOMPARE(t, MoveDefinedQString("Hello")); + QCOMPARE(s, MoveDefinedQString()); + + MoveDefinedQString &&r = std::move(t); // no actual move! + QCOMPARE(r, MoveDefinedQString("Hello")); + QCOMPARE(t, MoveDefinedQString("Hello")); // so 't' is unchanged + } - s = t; - t = std::move(s); - QCOMPARE(t, QString("Hello")); + // we require std::forward: + { + MoveDefinedQString s("Hello"); + MoveDefinedQString s2 = std::forward<MoveDefinedQString>(s); // forward as rvalue + QCOMPARE(s2, MoveDefinedQString("Hello")); + QCOMPARE(s, MoveDefinedQString()); + + MoveDefinedQString s3 = std::forward<MoveDefinedQString&>(s2); // forward as lvalue + QCOMPARE(s2, MoveDefinedQString("Hello")); + QCOMPARE(s3, MoveDefinedQString("Hello")); + } - QString &&r = std::move(s); - QCOMPARE(r, QString("Hello")); + // supported by MSVC only from November 2013 CTP, but only check for VC2015: +# if !defined(Q_CC_MSVC) || defined(Q_CC_INTEL) || _MSC_VER >= 1900 // VS14 == VC2015 + // we require automatic generation of move special member functions: + { + struct M { MoveDefinedQString s1, s2; }; + M m1 = { MoveDefinedQString("Hello"), MoveDefinedQString("World") }; + QCOMPARE(m1.s1, MoveDefinedQString("Hello")); + QCOMPARE(m1.s2, MoveDefinedQString("World")); + M m2 = std::move(m1); + QCOMPARE(m1.s1, MoveDefinedQString()); + QCOMPARE(m1.s2, MoveDefinedQString()); + QCOMPARE(m2.s1, MoveDefinedQString("Hello")); + QCOMPARE(m2.s2, MoveDefinedQString("World")); + M m3; + QCOMPARE(m3.s1, MoveDefinedQString()); + QCOMPARE(m3.s2, MoveDefinedQString()); + m3 = std::move(m2); + QCOMPARE(m2.s1, MoveDefinedQString()); + QCOMPARE(m2.s2, MoveDefinedQString()); + QCOMPARE(m3.s1, MoveDefinedQString("Hello")); + QCOMPARE(m3.s2, MoveDefinedQString("World")); + } +# endif // MSVC < 2015 #endif } |