1// Copyright (C) 2022 The Qt Company Ltd.
2// Copyright (C) 2019 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#ifndef QFOREACH_H
6#define QFOREACH_H
7
8#include <QtCore/qtclasshelpermacros.h>
9#include <QtCore/qtconfigmacros.h>
10#include <QtCore/qtdeprecationmarkers.h>
11#include <QtCore/qttypetraits.h>
12
13QT_BEGIN_NAMESPACE
14
15#if 0
16#pragma qt_class(QForeach)
17#pragma qt_sync_stop_processing
18#endif
19
20#ifndef QT_NO_FOREACH
21
22namespace QtPrivate {
23
24template <typename T>
25class QForeachContainer {
26 Q_DISABLE_COPY_MOVE(QForeachContainer)
27public:
28 QForeachContainer(const T &t) : c(t), i(std::as_const(c).begin()), e(std::as_const(c).end()) {}
29 QForeachContainer(T &&t) : c(std::move(t)), i(std::as_const(c).begin()), e(std::as_const(c).end()) {}
30
31 T c;
32 typename T::const_iterator i, e;
33};
34
35// Containers that have a detach function are considered shared, and are OK in a foreach loop
36template <typename T, typename = decltype(std::declval<T>().detach())>
37inline void warnIfContainerIsNotShared(int) {}
38
39#if QT_DEPRECATED_SINCE(6, 0)
40// Other containers will copy themselves if used in foreach, this use is deprecated
41template <typename T>
42QT_DEPRECATED_VERSION_X_6_0("Do not use foreach/Q_FOREACH with containers which are not implicitly shared. "
43 "Prefer using a range-based for loop with these containers: `for (const auto &it : container)`, "
44 "keeping in mind that range-based for doesn't copy the container as Q_FOREACH does")
45inline void warnIfContainerIsNotShared(...) {}
46#endif
47
48template<typename T>
49QForeachContainer<typename std::decay<T>::type> qMakeForeachContainer(T &&t)
50{
51 warnIfContainerIsNotShared<typename std::decay<T>::type>(0);
52 return QForeachContainer<typename std::decay<T>::type>(std::forward<T>(t));
53}
54
55}
56
57// Use C++17 if statement with initializer. User's code ends up in a else so
58// scoping of different ifs is not broken
59#define Q_FOREACH_IMPL(variable, name, container) \
60 for (auto name = QtPrivate::qMakeForeachContainer(container); name.i != name.e; ++name.i) \
61 if (variable = *name.i; false) {} else
62
63#define Q_FOREACH_JOIN(A, B) Q_FOREACH_JOIN_IMPL(A, B)
64#define Q_FOREACH_JOIN_IMPL(A, B) A ## B
65
66#define Q_FOREACH(variable, container) \
67 Q_FOREACH_IMPL(variable, Q_FOREACH_JOIN(_container_, __LINE__), container)
68#endif // QT_NO_FOREACH
69
70#define Q_FOREVER for(;;)
71#ifndef QT_NO_KEYWORDS
72# ifndef QT_NO_FOREACH
73# ifndef foreach
74# define foreach Q_FOREACH
75# endif
76# endif // QT_NO_FOREACH
77# ifndef forever
78# define forever Q_FOREVER
79# endif
80#endif
81
82QT_END_NAMESPACE
83
84#endif /* QFOREACH_H */
85

source code of qtbase/src/corelib/global/qforeach.h