From 90fab1e4e98962ecaff5fd66d218d4f76cb7b8cd Mon Sep 17 00:00:00 2001 From: Ivan Solovev Date: Thu, 19 Dec 2024 16:02:14 +0100 Subject: [PATCH] Fix QtFuture::when{All,Any}() overload resolution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both whenAll() and whenAny() have two overloads: * an overload taking two input iterators, e.g. whenAll(IntpuIt begin, InputIt end) * an overload taking an arbitrary number of future objects, e.g. whenAll(Futures &&... futures) The public APIs are properly constrained, but internally they call QtPrivate::when*Impl() template functions, that have the same two overloads, but do not have any constraints. As a result, passing exactly two QFuture{} objects was leading to the compiler picking the Impl overload that takes a pair of iterators. Fix it by applying a subset of constraints from the public API to the private implementation as well. Amends 102f7d31c469a546f52c930a047bd294fb198186 which was introduced for Qt 6.3, so picking down to Qt 6.5. Fixes: QTBUG-131959 Pick-to: 6.8 6.5 Change-Id: Ide29ac9a494d07870e92957c40c1f614e56825f8 Reviewed-by: MÃ¥rten Nordheim (cherry picked from commit 8aef5b0d8fd57684abe39c88af8c14d8882ef07b) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/thread/qfuture_impl.h | 8 ++++++-- tests/auto/corelib/thread/qfuture/tst_qfuture.cpp | 9 +++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/corelib/thread/qfuture_impl.h b/src/corelib/thread/qfuture_impl.h index 780e39dd8cb..01afa64cd6e 100644 --- a/src/corelib/thread/qfuture_impl.h +++ b/src/corelib/thread/qfuture_impl.h @@ -1106,7 +1106,9 @@ void addCompletionHandlers(const std::shared_ptr &context, const st addCompletionHandlersImpl(context, t); } -template +template, isQFuture>, + bool> = true> QFuture whenAllImpl(InputIt first, InputIt last) { const qsizetype size = std::distance(first, last); @@ -1142,7 +1144,9 @@ QFuture whenAllImpl(Futures &&... futures) return context->promise.future(); } -template +template, isQFuture>, + bool> = true> QFuture::type>> whenAnyImpl(InputIt first, InputIt last) { diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp index 7a8cd707d7c..b3c5f757416 100644 --- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp +++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp @@ -233,6 +233,7 @@ private slots: void getFutureInterface(); void convertQMetaType(); + void whenAllwhenAnyOverloadResolution(); void whenAllIterators(); void whenAllIteratorsWithCanceled(); void whenAllIteratorsWithFailed(); @@ -4447,6 +4448,14 @@ void tst_QFuture::convertQMetaType() QVERIFY(voidFuture.isFinished()); } +void tst_QFuture::whenAllwhenAnyOverloadResolution() +{ + // Compile-only test. These could fail to compile due to picking a wrong + // overload of *Impl() methods. See QTBUG-131959 + [[maybe_unused]] auto f = QtFuture::whenAll(QFuture{}, QFuture{}); + [[maybe_unused]] auto ff = QtFuture::whenAny(QFuture{}, QFuture{}); +} + template void testWhenAllIterators() {