diff options
Diffstat (limited to 'src/corelib/global/qforeach.h')
-rw-r--r-- | src/corelib/global/qforeach.h | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/corelib/global/qforeach.h b/src/corelib/global/qforeach.h new file mode 100644 index 0000000000..ab0e20b989 --- /dev/null +++ b/src/corelib/global/qforeach.h @@ -0,0 +1,84 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// Copyright (C) 2019 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QFOREACH_H +#define QFOREACH_H + +#include <QtCore/qtclasshelpermacros.h> +#include <QtCore/qtconfigmacros.h> +#include <QtCore/qtdeprecationmarkers.h> +#include <QtCore/qttypetraits.h> + +QT_BEGIN_NAMESPACE + +#if 0 +#pragma qt_class(QForeach) +#pragma qt_sync_stop_processing +#endif + +#ifndef QT_NO_FOREACH + +namespace QtPrivate { + +template <typename T> +class QForeachContainer { + Q_DISABLE_COPY_MOVE(QForeachContainer) +public: + QForeachContainer(const T &t) : c(t), i(std::as_const(c).begin()), e(std::as_const(c).end()) {} + QForeachContainer(T &&t) : c(std::move(t)), i(std::as_const(c).begin()), e(std::as_const(c).end()) {} + + T c; + typename T::const_iterator i, e; +}; + +// Containers that have a detach function are considered shared, and are OK in a foreach loop +template <typename T, typename = decltype(std::declval<T>().detach())> +inline void warnIfContainerIsNotShared(int) {} + +#if QT_DEPRECATED_SINCE(6, 0) +// Other containers will copy themselves if used in foreach, this use is deprecated +template <typename T> +QT_DEPRECATED_VERSION_X_6_0("Do not use foreach/Q_FOREACH with containers which are not implicitly shared. " + "Prefer using a range-based for loop with these containers: `for (const auto &it : container)`, " + "keeping in mind that range-based for doesn't copy the container as Q_FOREACH does") +inline void warnIfContainerIsNotShared(...) {} +#endif + +template<typename T> +QForeachContainer<typename std::decay<T>::type> qMakeForeachContainer(T &&t) +{ + warnIfContainerIsNotShared<typename std::decay<T>::type>(0); + return QForeachContainer<typename std::decay<T>::type>(std::forward<T>(t)); +} + +} + +// Use C++17 if statement with initializer. User's code ends up in a else so +// scoping of different ifs is not broken +#define Q_FOREACH_IMPL(variable, name, container) \ + for (auto name = QtPrivate::qMakeForeachContainer(container); name.i != name.e; ++name.i) \ + if (variable = *name.i; false) {} else + +#define Q_FOREACH_JOIN(A, B) Q_FOREACH_JOIN_IMPL(A, B) +#define Q_FOREACH_JOIN_IMPL(A, B) A ## B + +#define Q_FOREACH(variable, container) \ + Q_FOREACH_IMPL(variable, Q_FOREACH_JOIN(_container_, __LINE__), container) +#endif // QT_NO_FOREACH + +#define Q_FOREVER for(;;) +#ifndef QT_NO_KEYWORDS +# ifndef QT_NO_FOREACH +# ifndef foreach +# define foreach Q_FOREACH +# endif +# endif // QT_NO_FOREACH +# ifndef forever +# define forever Q_FOREVER +# endif +#endif + +QT_END_NAMESPACE + +#endif /* QFOREACH_H */ |