From fa4d18b86c0cb0de495ce988fd9d3714e09b05dd Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 10 Jun 2022 08:07:22 +0200 Subject: [PATCH] Revert "qxp::function_ref: drop use of q23::invoke_r" This reverts commit b9cce12e76796962e5e5ad0d5408370af56af459, which broke function_ref f = [](int i) { return i; }; ie. swallowing of return types. We could maybe implement the same without invoke_r, with the same manual if-constexpr that invoke_r has, but it would be a pointless duplication across the two thunks we have, so just use invoke_r. Add tests. Pick-to: 6.4 Task-number: QTBUG-103739 Change-Id: I6034f05d813c06a25e8058ded5b6b62f3ca858b4 Reviewed-by: Fabian Kosmale --- src/corelib/global/qxpfunctional.h | 8 ++-- .../qxp/function_ref/tst_qxp_function_ref.cpp | 40 +++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/corelib/global/qxpfunctional.h b/src/corelib/global/qxpfunctional.h index ca015be22e..67350c56ed 100644 --- a/src/corelib/global/qxpfunctional.h +++ b/src/corelib/global/qxpfunctional.h @@ -21,7 +21,7 @@ // We mean it. // -#include +#include #include #include @@ -99,7 +99,8 @@ public: Q_IMPLICIT function_ref_base(F* f) noexcept : m_bound_entity(f), m_thunk_ptr([](BoundEntityType ctx, ArgTypes&&... args) noexcept(noex) -> R { - return reinterpret_cast(ctx.fun)(std::forward(args)...); + return q23::invoke_r(reinterpret_cast(ctx.fun), + std::forward(args)...); }) {} @@ -115,7 +116,8 @@ public: : m_bound_entity(std::addressof(f)), m_thunk_ptr([](BoundEntityType ctx, ArgTypes&&... args) noexcept(noex) -> R { using That = copy_const_t>; - return (*static_cast(ctx.obj))(std::forward(args)...); + return q23::invoke_r(*static_cast(ctx.obj), + std::forward(args)...); }) {} diff --git a/tests/auto/corelib/global/qxp/function_ref/tst_qxp_function_ref.cpp b/tests/auto/corelib/global/qxp/function_ref/tst_qxp_function_ref.cpp index b17ead436a..be83e76f18 100644 --- a/tests/auto/corelib/global/qxp/function_ref/tst_qxp_function_ref.cpp +++ b/tests/auto/corelib/global/qxp/function_ref/tst_qxp_function_ref.cpp @@ -42,6 +42,7 @@ private Q_SLOTS: void basics(); void constOverloads(); void constExpr(); + void voidReturning(); void ctad(); }; @@ -195,6 +196,45 @@ void v_f_i_ex(int) {} int i_f_v_ex() { return 42; } void v_f_v_ex() {} +void tst_qxp_function_ref::voidReturning() +{ + // check that "casting" int to void returns works: + + using Fi = qxp::function_ref; + using Fv = qxp::function_ref; + + { + Fi fi = i_f_i_nx; + fi(42); + Fv fv = i_f_v_nx; + fv(); + } + + { + Fi fi = i_f_i_ex; + fi(42); + Fv fv = i_f_v_ex; + fv(); + } + + // now with lambdas + + bool ok = false; // prevent lambdas from decaying to function pointers + { + Fi fi = [&](int i) noexcept { return i + int(ok); }; + fi(42); + Fv fv = [&]() noexcept { return int(ok); }; + fv(); + } + + { + Fi fi = [&](int i) { return i + int(ok); }; + fi(42); + Fv fv = [&]() { return int(ok); }; + fv(); + } +} + void tst_qxp_function_ref::ctad() { #define CHECK(fun, sig) \