summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Mutz <[email protected]>2025-06-24 16:09:12 +0200
committerMarc Mutz <[email protected]>2025-06-27 17:21:45 +0200
commitec24625373c680fd51237b809792e9cd98c792f0 (patch)
tree76ce2e3e8952a6453e8907a48124be260c145457
parentf12d046383decf8f468de62732c9cff7d4303cbf (diff)
QObject: Extract Method q_choose_{assign,append} from doSetProperty()
We'll apply that doSetFoo() pattern in more places going forward, so extract the central switch between lvalue and rvalue into a pair of class helper functions for easier reuse. Needed a new header for this, so started a qtclasshelper_p.h. Amends 39cdf431f034121353e51768b4d1fec8b0dd35dc. Pick-to: 6.10 6.9 6.8 Change-Id: I864b7faba41a74058e42d2ca96a0cc519751389f Reviewed-by: Ivan Solovev <[email protected]> Reviewed-by: Thiago Macieira <[email protected]>
-rw-r--r--src/corelib/CMakeLists.txt1
-rw-r--r--src/corelib/global/qtclasshelper_p.h77
-rw-r--r--src/corelib/kernel/qobject.cpp11
3 files changed, 81 insertions, 8 deletions
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index af7173b72d5..4d83bbf794e 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -77,6 +77,7 @@ qt_internal_add_module(Core
global/qsysinfo.cpp global/qsysinfo.h
global/qsystemdetection.h
global/qtclasshelpermacros.h
+ global/qtclasshelper_p.h
global/qtconfiginclude.h
global/qtconfigmacros.h
global/qtcoreglobal.h global/qtcoreglobal_p.h
diff --git a/src/corelib/global/qtclasshelper_p.h b/src/corelib/global/qtclasshelper_p.h
new file mode 100644
index 00000000000..1e356726126
--- /dev/null
+++ b/src/corelib/global/qtclasshelper_p.h
@@ -0,0 +1,77 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
+
+#ifndef QTCLASSHELPER_P_H
+#define QTCLASSHELPER_P_H
+
+#include <QtCore/private/qglobal_p.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <type_traits>
+#include <utility>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Helper for setters overloaded on lvalue/rvalue. If the setter is doing a
+ lot of work around the actual assignment, a common pattern is to create a
+ private helper method
+
+ void doSetFoo(const Foo &lvalue, Foo *rvalue);
+
+ and implement the two setters inline by calling that function:
+
+ void setFoo(const Foo &f) { doSetFoo(f, nullptr); }
+ void setFoo(Foo &&f) { doSetFoo(f, &f); }
+
+ Then, in doSetFoo(), when assigning the argument to the member, use this
+ function:
+
+ q_choose_assign(m_foo, lvalue, rvalue);
+
+ or, when appending to a container,
+
+ q_choose_append(m_container, lvalue, rvalue);
+
+ The functions mandate (in the C++ sense) that all arguments are the same
+ type, so they deduce each argument separately and then static_assert that
+ they're the same. If we need std::exchange()-like mixed types later, it's
+ easy to relax. For now, avoid being overly general.
+*/
+template <typename T, typename U, typename V>
+decltype(auto) q_choose_assign(T &var, const U &lvalue, V *rvalue)
+{
+ static_assert(std::is_same_v<T, U>, "all arguments must be of the same type");
+ static_assert(std::is_same_v<U, V>, "all arguments must be of the same type");
+ if (rvalue)
+ return var = std::move(*rvalue);
+ else
+ return var = lvalue;
+}
+
+template <typename Container, typename U, typename V>
+decltype(auto) q_choose_append(Container &c, const U &lvalue, V *rvalue)
+{
+ static_assert(std::is_same_v<typename Container::value_type, U>, "arguments must match container");
+ static_assert(std::is_same_v<U, V>, "all arguments must be of the same type");
+ if (rvalue)
+ c.push_back(std::move(*rvalue));
+ else
+ c.push_back(lvalue);
+ return c.back();
+}
+
+QT_END_NAMESPACE
+
+#endif // QTCLASSHELPER_P_H
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 0d2ec8efd7a..5a6da48d52c 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -8,6 +8,7 @@
#include "qobject_p_p.h"
#include "qmetaobject_p.h"
+#include <QtCore/private/qtclasshelper_p.h>
#include "qabstracteventdispatcher.h"
#include "qabstracteventdispatcher_p.h"
#include "qcoreapplication.h"
@@ -4392,18 +4393,12 @@ bool QObject::doSetProperty(const char *name, const QVariant *lvalue, QVariant *
} else {
if (idx == -1) {
d->extraData->propertyNames.append(name);
- if (rvalue)
- d->extraData->propertyValues.append(std::move(*rvalue));
- else
- d->extraData->propertyValues.append(*lvalue);
+ q_choose_append(d->extraData->propertyValues, value, rvalue);
} else {
if (value.userType() == d->extraData->propertyValues.at(idx).userType()
&& value == d->extraData->propertyValues.at(idx))
return false;
- if (rvalue)
- d->extraData->propertyValues[idx] = std::move(*rvalue);
- else
- d->extraData->propertyValues[idx] = *lvalue;
+ q_choose_assign(d->extraData->propertyValues[idx], value, rvalue);
}
}