diff options
author | Marc Mutz <[email protected]> | 2025-06-24 16:09:12 +0200 |
---|---|---|
committer | Marc Mutz <[email protected]> | 2025-06-27 17:21:45 +0200 |
commit | ec24625373c680fd51237b809792e9cd98c792f0 (patch) | |
tree | 76ce2e3e8952a6453e8907a48124be260c145457 | |
parent | f12d046383decf8f468de62732c9cff7d4303cbf (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.txt | 1 | ||||
-rw-r--r-- | src/corelib/global/qtclasshelper_p.h | 77 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 11 |
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); } } |