Created
May 19, 2020 06:19
-
-
Save kraj/183347465a873905e68807a5791a4c21 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From c35a3f519007af44c3b364b9af86f6a336f6411b Mon Sep 17 00:00:00 2001 | |
From: Thiago Macieira <thiago.macieira@intel.com> | |
Date: Tue, 11 Feb 2014 16:17:46 -0800 | |
Subject: [PATCH] Redo the Q_FOREACH loop control without GCC statement | |
expressions | |
It's possible to do without them, which probably makes the number of | |
supported compilers a lot bigger: they just need to support decltype() | |
or __typeof__. | |
That includes the Intel compiler. The old code was also apparently | |
working, but no one had realized the old workaround for some old version | |
was still in place. | |
The loop overhead is more or less the same. I have not done benchmarks, | |
but inspection of the generated assembly shows more or less the same | |
number of instructions. | |
Change-Id: I32d499c84a6ddd19d994b49f17a469acb5c3a3f1 | |
Reviewed-by: Olivier Goffart <ogoffart@woboq.com> | |
Reviewed-by: Marc Mutz <marc.mutz@kdab.com> | |
--- | |
src/corelib/global/qglobal.h | 24 +++++++++++++++++------- | |
1 file changed, 17 insertions(+), 7 deletions(-) | |
Index: git/source/qtbase/src/corelib/global/qglobal.h | |
=================================================================== | |
--- git.orig/source/qtbase/src/corelib/global/qglobal.h | |
+++ git/source/qtbase/src/corelib/global/qglobal.h | |
@@ -809,22 +809,31 @@ Q_CORE_EXPORT void qFreeAligned(void *pt | |
# endif | |
#endif | |
-#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_RVCT) | |
+#if (defined(Q_CC_GNU) && !defined(Q_CC_RVCT)) | |
/* make use of typeof-extension */ | |
template <typename T> | |
class QForeachContainer { | |
public: | |
- inline QForeachContainer(const T& t) : c(t), brk(0), i(c.begin()), e(c.end()) { } | |
+ inline QForeachContainer(const T& t) : c(t), i(c.begin()), e(c.end()), control(1) { } | |
const T c; | |
- int brk; | |
typename T::const_iterator i, e; | |
+ int control; | |
}; | |
-#define Q_FOREACH(variable, container) \ | |
+// Explanation of the control word: | |
+// - it's initialized to 1 | |
+// - that means both the inner and outer loops start | |
+// - if there were no breaks, at the end of the inner loop, it's set to 0, which | |
+// causes it to exit (the inner loop is run exactly once) | |
+// - at the end of the outer loop, it's inverted, so it becomes 1 again, allowing | |
+// the outer loop to continue executing | |
+// - if there was a break inside the inner loop, it will exit with control still | |
+// set to 1; in that case, the outer loop will invert it to 0 and will exit too | |
+# define Q_FOREACH(variable, container) \ | |
for (QForeachContainer<__typeof__(container)> _container_(container); \ | |
- !_container_.brk && _container_.i != _container_.e; \ | |
- __extension__ ({ ++_container_.brk; ++_container_.i; })) \ | |
- for (variable = *_container_.i;; __extension__ ({--_container_.brk; break;})) | |
+ _container_.control && _container_.i != _container_.e; \ | |
+ ++_container_.i, _container_.control ^= 1) \ | |
+ for (variable = *_container_.i; _container_.control; _container_.control = 0) | |
#else | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment