summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2013-11-13 11:37:37 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-17 09:47:07 +0100
commit3e803b5180e7059c01c15ea84cadd54982e1a221 (patch)
tree4ce472724bf7ef840c270f89e9ccffac523b36ae
parent6c04c21c101b70401ad9cb08de1562dc90166e9c (diff)
QCollator: enable move semantics
This necessitates adding d==0 checks in QCollator. By documenting that moved-from instances can only be assigned to or destroyed, we can limit the functions in which to check for d==0 to the assignment operator and the destructor. Doing otherwise would destroy all advantages of move semantics by introducing a heap allocation to re-populate other.d. Add a test for this (QCollator didn't have any before). Change-Id: Ic6ff202072822bebfd5e48259c3d0fa345a63118 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/tools/qcollator.cpp26
-rw-r--r--src/corelib/tools/qcollator.h6
-rw-r--r--tests/auto/corelib/tools/qcollator/qcollator.pro7
-rw-r--r--tests/auto/corelib/tools/qcollator/tst_qcollator.cpp92
-rw-r--r--tests/auto/corelib/tools/tools.pro1
5 files changed, 129 insertions, 3 deletions
diff --git a/src/corelib/tools/qcollator.cpp b/src/corelib/tools/qcollator.cpp
index cfb5fe77ae..80d330bfca 100644
--- a/src/corelib/tools/qcollator.cpp
+++ b/src/corelib/tools/qcollator.cpp
@@ -99,7 +99,7 @@ QCollator::QCollator(const QCollator &other)
*/
QCollator::~QCollator()
{
- if (!d->ref.deref())
+ if (d && !d->ref.deref())
delete d;
}
@@ -109,14 +109,34 @@ QCollator::~QCollator()
QCollator &QCollator::operator=(const QCollator &other)
{
if (this != &other) {
- if (!d->ref.deref())
+ if (d && !d->ref.deref())
delete d;
d = other.d;
- d->ref.ref();
+ if (d) d->ref.ref();
}
return *this;
}
+/*
+ \fn void QCollator::QCollator(QCollator &&other)
+
+ Move constructor. Moves from \a other into this collator.
+
+ Note that a moved-from QCollator can only be destroyed or assigned
+ to. The effect of calling other functions than the destructor or
+ one of the assignment operators is undefined.
+*/
+
+/*
+ \fn QCollator &QCollator::operator=(QCollator &&other)
+
+ Move-assigns from \a other to this collator.
+
+ Note that a moved-from QCollator can only be destroyed or assigned
+ to. The effect of calling other functions than the destructor or
+ one of the assignment operators is undefined.
+*/
+
/*!
\fn void QCollator::swap(QCollator &other)
diff --git a/src/corelib/tools/qcollator.h b/src/corelib/tools/qcollator.h
index e5abc91967..1007aa7623 100644
--- a/src/corelib/tools/qcollator.h
+++ b/src/corelib/tools/qcollator.h
@@ -85,6 +85,12 @@ public:
QCollator(const QCollator &);
~QCollator();
QCollator &operator=(const QCollator &);
+#ifdef Q_COMPILER_RVALUE_REFS
+ QCollator(QCollator &&other)
+ : d(other.d) { other.d = 0; }
+ QCollator &operator=(QCollator &&other)
+ { swap(other); return *this; }
+#endif
void swap(QCollator &other)
{ qSwap(d, other.d); }
diff --git a/tests/auto/corelib/tools/qcollator/qcollator.pro b/tests/auto/corelib/tools/qcollator/qcollator.pro
new file mode 100644
index 0000000000..3c5987ffa0
--- /dev/null
+++ b/tests/auto/corelib/tools/qcollator/qcollator.pro
@@ -0,0 +1,7 @@
+CONFIG += testcase parallel_test
+TARGET = tst_qcollator
+QT = core testlib
+SOURCES = tst_qcollator.cpp
+DEFINES += QT_NO_CAST_TO_ASCII
+contains(QT_CONFIG,icu):DEFINES += QT_USE_ICU
+DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp b/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp
new file mode 100644
index 0000000000..3df8422a34
--- /dev/null
+++ b/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <qlocale.h>
+#include <qcollator.h>
+
+#include <cstring>
+
+class tst_QCollator : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void moveSemantics();
+};
+
+#ifdef Q_COMPILER_RVALUE_REFS
+static bool dpointer_is_null(QCollator &c)
+{
+ char mem[sizeof c];
+ using namespace std;
+ memcpy(mem, &c, sizeof c);
+ for (size_t i = 0; i < sizeof c; ++i)
+ if (mem[i])
+ return false;
+ return true;
+}
+#endif
+
+void tst_QCollator::moveSemantics()
+{
+#ifdef Q_COMPILER_RVALUE_REFS
+ const QLocale de_AT(QLocale::German, QLocale::Austria);
+
+ QCollator c1(de_AT);
+ QCOMPARE(c1.locale(), de_AT);
+
+ QCollator c2(std::move(c1));
+ QCOMPARE(c2.locale(), de_AT);
+ QVERIFY(dpointer_is_null(c1));
+
+ c1 = std::move(c2);
+ QCOMPARE(c1.locale(), de_AT);
+ QVERIFY(dpointer_is_null(c2));
+#else
+ QSKIP("The compiler is not in C++11 mode or does not support move semantics.");
+#endif
+}
+
+QTEST_APPLESS_MAIN(tst_QCollator)
+
+#include "tst_qcollator.moc"
diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro
index e920813db2..286afdfd18 100644
--- a/tests/auto/corelib/tools/tools.pro
+++ b/tests/auto/corelib/tools/tools.pro
@@ -8,6 +8,7 @@ SUBDIRS=\
qbytedatabuffer \
qcache \
qchar \
+ qcollator \
qcommandlineparser \
qcontiguouscache \
qcryptographichash \