QtFuture::connect: exclude QPrivateSignal from the resulting future type
Filter out the last argument of type QPrivateSignal from the signal's arguments passed to QtFuture::connect(). Pick-to: 6.2 Fixes: QTBUG-92501 Change-Id: Idcd6baba1f01fcc94fa64b1c7030a629d01ed7a1 Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>bb10
parent
799660d679
commit
ed546ff216
|
|
@ -129,7 +129,48 @@ struct ResultTypeHelper<
|
|||
using ResultType = std::invoke_result_t<std::decay_t<F>>;
|
||||
};
|
||||
|
||||
// Helpers to remove QPrivateSignal argument from the list of arguments
|
||||
|
||||
template<class T, class Enable = void>
|
||||
inline constexpr bool IsPrivateSignalArg = false;
|
||||
|
||||
template<class T>
|
||||
inline constexpr bool IsPrivateSignalArg<T, typename std::enable_if_t<
|
||||
// finds injected-class-name, the 'class' avoids falling into the rules of [class.qual]/2:
|
||||
std::is_class_v<class T::QPrivateSignal>
|
||||
>> = true;
|
||||
|
||||
template<class Tuple, std::size_t... I>
|
||||
auto cutTuple(Tuple &&t, std::index_sequence<I...>)
|
||||
{
|
||||
return std::make_tuple(std::get<I>(t)...);
|
||||
}
|
||||
|
||||
template<class Arg, class... Args>
|
||||
auto createTuple(Arg &&arg, Args &&... args)
|
||||
{
|
||||
using TupleType = std::tuple<std::decay_t<Arg>, std::decay_t<Args>...>;
|
||||
constexpr auto Size = sizeof...(Args); // One less than the size of all arguments
|
||||
if constexpr (QtPrivate::IsPrivateSignalArg<std::tuple_element_t<Size, TupleType>>) {
|
||||
if constexpr (Size == 1) {
|
||||
return arg;
|
||||
} else {
|
||||
return cutTuple(std::make_tuple(std::forward<Arg>(arg), std::forward<Args>(args)...),
|
||||
std::make_index_sequence<Size>());
|
||||
}
|
||||
} else {
|
||||
return std::make_tuple(std::forward<Arg>(arg), std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers to resolve argument types of callables.
|
||||
|
||||
template<class Arg, class... Args>
|
||||
using FilterLastPrivateSignalArg =
|
||||
std::conditional_t<(sizeof...(Args) > 0),
|
||||
std::invoke_result_t<decltype(createTuple<Arg, Args...>), Arg, Args...>,
|
||||
std::conditional_t<IsPrivateSignalArg<Arg>, void, Arg>>;
|
||||
|
||||
template<typename...>
|
||||
struct ArgsType;
|
||||
|
||||
|
|
@ -140,9 +181,7 @@ struct ArgsType<Arg, Args...>
|
|||
using PromiseType = void;
|
||||
using IsPromise = std::false_type;
|
||||
static const bool HasExtraArgs = (sizeof...(Args) > 0);
|
||||
using AllArgs =
|
||||
std::conditional_t<HasExtraArgs, std::tuple<std::decay_t<Arg>, std::decay_t<Args>...>,
|
||||
std::decay_t<Arg>>;
|
||||
using AllArgs = FilterLastPrivateSignalArg<std::decay_t<Arg>, std::decay_t<Args>...>;
|
||||
|
||||
template<class Class, class Callable>
|
||||
static const bool CanInvokeWithArgs = std::is_invocable_v<Callable, Class, Arg, Args...>;
|
||||
|
|
@ -155,9 +194,7 @@ struct ArgsType<QPromise<Arg> &, Args...>
|
|||
using PromiseType = Arg;
|
||||
using IsPromise = std::true_type;
|
||||
static const bool HasExtraArgs = (sizeof...(Args) > 0);
|
||||
using AllArgs =
|
||||
std::conditional_t<HasExtraArgs, std::tuple<std::decay_t<QPromise<Arg> &>, std::decay_t<Args>...>,
|
||||
std::decay_t<QPromise<Arg> &>>;
|
||||
using AllArgs = FilterLastPrivateSignalArg<QPromise<Arg>, std::decay_t<Args>...>;
|
||||
|
||||
template<class Class, class Callable>
|
||||
static const bool CanInvokeWithArgs = std::is_invocable_v<Callable, Class, QPromise<Arg> &, Args...>;
|
||||
|
|
@ -899,7 +936,8 @@ static QFuture<ArgsType<Signal>> connect(Sender *sender, Signal signal)
|
|||
[promise, connections](auto... values) mutable {
|
||||
QObject::disconnect(connections->first);
|
||||
QObject::disconnect(connections->second);
|
||||
promise.reportResult(std::make_tuple(values...));
|
||||
promise.reportResult(QtPrivate::createTuple(
|
||||
std::move(values)...));
|
||||
promise.reportFinished();
|
||||
});
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -70,11 +70,23 @@ public:
|
|||
emit multipleArgs(value1, value2, value3);
|
||||
}
|
||||
|
||||
void emitNoArgPrivateSignal() { emit noArgPrivateSignal(QPrivateSignal()); }
|
||||
void emitIntArgPrivateSignal(int value) { emit intArgPrivateSignal(value, QPrivateSignal()); }
|
||||
void emitMultiArgsPrivateSignal(int value1, double value2, const QString &value3)
|
||||
{
|
||||
emit multiArgsPrivateSignal(value1, value2, value3, QPrivateSignal());
|
||||
}
|
||||
|
||||
signals:
|
||||
void noArgSignal();
|
||||
void intArgSignal(int value);
|
||||
void constRefArg(const QString &value);
|
||||
void multipleArgs(int value1, double value2, const QString &value3);
|
||||
|
||||
// Private signals
|
||||
void noArgPrivateSignal(QPrivateSignal);
|
||||
void intArgPrivateSignal(int value, QPrivateSignal);
|
||||
void multiArgsPrivateSignal(int value1, double value2, const QString &value3, QPrivateSignal);
|
||||
};
|
||||
|
||||
class LambdaThread : public QThread
|
||||
|
|
@ -3433,7 +3445,7 @@ void tst_QFuture::signalConnect()
|
|||
{
|
||||
SenderObject sender;
|
||||
auto future =
|
||||
QtFuture::connect(&sender, &SenderObject::noArgSignal).then([&] { return true; });
|
||||
QtFuture::connect(&sender, &SenderObject::noArgSignal).then([] { return true; });
|
||||
sender.emitNoArg();
|
||||
QCOMPARE(future.result(), true);
|
||||
}
|
||||
|
|
@ -3474,6 +3486,39 @@ void tst_QFuture::signalConnect()
|
|||
QCOMPARE(std::get<2>(result), "42");
|
||||
}
|
||||
|
||||
// No arg private signal
|
||||
{
|
||||
SenderObject sender;
|
||||
auto future = QtFuture::connect(&sender, &SenderObject::noArgPrivateSignal).then([] {
|
||||
return true;
|
||||
});
|
||||
sender.emitNoArgPrivateSignal();
|
||||
QCOMPARE(future.result(), true);
|
||||
}
|
||||
|
||||
// One arg private signal
|
||||
{
|
||||
SenderObject sender;
|
||||
auto future =
|
||||
QtFuture::connect(&sender, &SenderObject::intArgPrivateSignal).then([](int value) {
|
||||
return value;
|
||||
});
|
||||
sender.emitIntArgPrivateSignal(42);
|
||||
QCOMPARE(future.result(), 42);
|
||||
}
|
||||
|
||||
// Multi-args private signal
|
||||
{
|
||||
SenderObject sender;
|
||||
auto future = QtFuture::connect(&sender, &SenderObject::multiArgsPrivateSignal)
|
||||
.then([](std::tuple<int, double, QString> values) { return values; });
|
||||
sender.emitMultiArgsPrivateSignal(42, 42.5, "42");
|
||||
const auto [i, d, s] = future.result();
|
||||
QCOMPARE(i, 42);
|
||||
QCOMPARE(d, 42.5);
|
||||
QCOMPARE(s, "42");
|
||||
}
|
||||
|
||||
// Sender destroyed
|
||||
{
|
||||
SenderObject *sender = new SenderObject();
|
||||
|
|
|
|||
Loading…
Reference in New Issue