diff options
author | Olivier Goffart <ogoffart@woboq.com> | 2016-04-12 16:05:10 +0200 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@theqtcompany.com> | 2016-04-13 09:35:13 +0000 |
commit | dbe9a8c9696428529cacb9dd4e004db99914b56e (patch) | |
tree | 08cf5d401da1bd3ea23027383bc88793513c836a | |
parent | 3b98467ebe0e447d8343457310827e18706e9550 (diff) |
Don't copy the functor object for each signal emission
The behavior was different in the variadic template code and in the C++98
code. The code without variadic template support was not copying the functor
object (e.g. a lambda) before calling it.
However, in the variadic template section, QtPrivate::FunctorCall::call
took the functor by value instead of by reference resulting in a copy.
QtPrivate::FunctorCall::call is a helper function for
QtPrivate::FunctionPointer::call which is only needed for variadic template
expension.
[ChangeLog][QtCore][QObject] If the compiler supports variadic templates,
no longer copy functor connected to a signal each time the signal is
emitted. Restoring the C++98 behavior.
Task-number: QTBUG-52542
Change-Id: I3ca20ef6910893b8a288e70af7de4c7b69502173
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r-- | src/corelib/kernel/qobjectdefs_impl.h | 2 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qobject/tst_qobject.cpp | 19 |
2 files changed, 20 insertions, 1 deletions
diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h index d5574a4dd1..922b6bbb42 100644 --- a/src/corelib/kernel/qobjectdefs_impl.h +++ b/src/corelib/kernel/qobjectdefs_impl.h @@ -491,7 +491,7 @@ namespace QtPrivate { template <typename, typename, typename, typename> struct FunctorCall; template <int... II, typename... SignalArgs, typename R, typename Function> struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, Function> { - static void call(Function f, void **arg) { + static void call(Function &f, void **arg) { f((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]); } }; diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index f3334b1222..5b89ef3792 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -147,6 +147,7 @@ private slots: void qmlConnect(); void exceptions(); void noDeclarativeParentChangedOnDestruction(); + void mutableFunctor(); }; struct QObjectCreatedOnShutdown @@ -6420,6 +6421,24 @@ void tst_QObject::noDeclarativeParentChangedOnDestruction() #endif } +struct MutableFunctor { + int count; + MutableFunctor() : count(0) {} + int operator()() { return ++count; } +}; + +void tst_QObject::mutableFunctor() +{ + ReturnValue o; + MutableFunctor functor; + QCOMPARE(functor.count, 0); + connect(&o, &ReturnValue::returnInt, functor); + QCOMPARE(emit o.returnInt(0), 1); + QCOMPARE(emit o.returnInt(0), 2); // each emit should increase the internal count + + QCOMPARE(functor.count, 0); // but the original object should have been copied at connect time +} + // Test for QtPrivate::HasQ_OBJECT_Macro Q_STATIC_ASSERT(QtPrivate::HasQ_OBJECT_Macro<tst_QObject>::Value); Q_STATIC_ASSERT(!QtPrivate::HasQ_OBJECT_Macro<SiblingDeleter>::Value); |