diff options
author | Olivier Goffart <ogoffart@woboq.com> | 2018-10-29 12:21:38 +0100 |
---|---|---|
committer | Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com> | 2018-10-31 09:07:49 +0000 |
commit | 0330b967f20bc265b9799418ce8e0b6faf929a62 (patch) | |
tree | b6b5adb7d7af617cbacbc8cec57bcd4d1fa07bf8 | |
parent | 22788194f93eeec53cd82380a5e0448579ea0930 (diff) |
Simplify the Q_FOREACH macro when using C++17
This way there is only one for loop, which is more optimizer friendly
Change-Id: Iaa02026627d5259c3eea1ff5664e8f22664eef73
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r-- | src/corelib/global/qglobal.h | 11 | ||||
-rw-r--r-- | tests/auto/corelib/global/qglobal/qglobal.pro | 1 | ||||
-rw-r--r-- | tests/auto/corelib/global/qglobal/tst_qglobal.cpp | 40 |
3 files changed, 51 insertions, 1 deletions
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index f56629faa1..8680742c94 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -1005,6 +1005,15 @@ QForeachContainer<typename std::decay<T>::type> qMakeForeachContainer(T &&t) } } + +#if __cplusplus >= 201703L +// 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(variable, container) \ +for (auto _container_ = QtPrivate::qMakeForeachContainer(container); \ + _container_.i != _container_.e; ++_container_.i) \ + if (variable = *_container_.i; false) {} else +#else // Explanation of the control word: // - it's initialized to 1 // - that means both the inner and outer loops start @@ -1019,7 +1028,7 @@ for (auto _container_ = QtPrivate::qMakeForeachContainer(container); \ _container_.control && _container_.i != _container_.e; \ ++_container_.i, _container_.control ^= 1) \ for (variable = *_container_.i; _container_.control; _container_.control = 0) - +#endif #endif // QT_NO_FOREACH #define Q_FOREVER for(;;) diff --git a/tests/auto/corelib/global/qglobal/qglobal.pro b/tests/auto/corelib/global/qglobal/qglobal.pro index a40cb9a288..b105769430 100644 --- a/tests/auto/corelib/global/qglobal/qglobal.pro +++ b/tests/auto/corelib/global/qglobal/qglobal.pro @@ -2,3 +2,4 @@ CONFIG += testcase TARGET = tst_qglobal QT = core testlib SOURCES = tst_qglobal.cpp qglobal.c +contains(QT_CONFIG, c++1z): CONFIG += c++1z diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp index 78b954f373..56da047147 100644 --- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp +++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp @@ -126,6 +126,46 @@ void tst_QGlobal::for_each() QCOMPARE(i, counter++); } QCOMPARE(counter, list.count()); + + // Should also work with an existing variable + int local; + counter = 0; + foreach (local, list) { + QCOMPARE(local, counter++); + } + QCOMPARE(counter, list.count()); + QCOMPARE(local, counter - 1); + + // Test the macro does not mess if/else conditions + counter = 0; + if (true) + foreach (int i, list) + QCOMPARE(i, counter++); + else + QFAIL("If/Else mismatch"); + QCOMPARE(counter, list.count()); + + counter = 0; + if (false) + foreach (int i, list) + if (i) QFAIL("If/Else mismatch"); + else QFAIL("If/Else mismatch"); + else + foreach (int i, list) + if (false) { } + else QCOMPARE(i, counter++); + QCOMPARE(counter, list.count()); + + // break and continue + counter = 0; + foreach (int i, list) { + if (i == 0) + continue; + QCOMPARE(i, (counter++) + 1); + if (i == 3) + break; + } + QCOMPARE(counter, 3); } void tst_QGlobal::qassert() |