From bc8e01df4286f5f8ff9103fbebad801f355db689 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 3 Jul 2022 22:14:13 +0200 Subject: Shorten switchOnType, function_traits and connect* ...thanks to C++20 awesomeness. A notable change is that wrap_in_function() (and respectively function_traits<>::function_type) and fn_return_t alias are gone. The former are no more needed because connectUntil/connectSingleShot no more use std::function. The latter has been relatively underused and with the optimisation of switchOnType hereby, could be completely replaced with std::invoke_result_t. Rewriting connect* functions using constexpr and auto parameters made the implementation 30% more compact and much easier to understand (though still with a couple of - now thoroughly commented - tricky places). Dropping std::function<> from it may also bring some (quite modest, likely) performance benefits. --- lib/events/event.h | 64 ++++++++++++++++++------------------------------------ 1 file changed, 21 insertions(+), 43 deletions(-) (limited to 'lib/events/event.h') diff --git a/lib/events/event.h b/lib/events/event.h index ec21c6aa..a966e613 100644 --- a/lib/events/event.h +++ b/lib/events/event.h @@ -341,56 +341,34 @@ inline auto eventCast(const BasePtrT& eptr) : nullptr; } -// A trivial generic catch-all "switch" -template -inline auto switchOnType(const BaseEventT& event, FnT&& fn) - -> decltype(fn(event)) -{ - return fn(event); -} - namespace _impl { - // Using bool instead of auto below because auto apparently upsets MSVC - template - constexpr bool needs_downcast = - std::is_base_of_v>> - && !std::is_same_v>>; -} - -// A trivial type-specific "switch" for a void function -template -inline auto switchOnType(const BaseT& event, FnT&& fn) - -> std::enable_if_t<_impl::needs_downcast - && std::is_void_v>> -{ - using event_type = fn_arg_t; - if (is>(event)) - fn(static_cast(event)); + template + concept Invocable_With_Downcast = + std::derived_from>, BaseT>; } -// A trivial type-specific "switch" for non-void functions with an optional -// default value; non-voidness is guarded by defaultValue type -template -inline auto switchOnType(const BaseT& event, FnT&& fn, - fn_return_t&& defaultValue = {}) - -> std::enable_if_t<_impl::needs_downcast, fn_return_t> +template +inline auto switchOnType(const BaseT& event, TailT&& tail) { - using event_type = fn_arg_t; - if (is>(event)) - return fn(static_cast(event)); - return std::move(defaultValue); + if constexpr (std::is_invocable_v) { + return tail(event); + } else if constexpr (_impl::Invocable_With_Downcast) { + using event_type = fn_arg_t; + if (is>(event)) + return tail(static_cast(event)); + return std::invoke_result_t(); // Default-constructed + } else { // Treat it as a value to return + return std::forward(tail); + } } -// A switch for a chain of 2 or more functions -template -inline std::common_type_t, fn_return_t> -switchOnType(const BaseT& event, FnT1&& fn1, FnT2&& fn2, FnTs&&... fns) +template +inline auto switchOnType(const BaseT& event, FnT1&& fn1, FnTs&&... fns) { using event_type1 = fn_arg_t; if (is>(event)) - return fn1(static_cast(event)); - return switchOnType(event, std::forward(fn2), - std::forward(fns)...); + return fn1(static_cast(event)); + return switchOnType(event, std::forward(fns)...); } template @@ -405,8 +383,8 @@ inline auto visit(const BaseT& event, FnTs&&... fns) // TODO: replace with ranges::for_each once all standard libraries have it template inline auto visitEach(RangeT&& events, FnTs&&... fns) - -> std::enable_if_t(fns)...))>> + requires std::is_void_v< + decltype(switchOnType(**begin(events), std::forward(fns)...))> { for (auto&& evtPtr: events) switchOnType(*evtPtr, std::forward(fns)...); -- cgit v1.2.3 From 64948b6840032b04ef00bfe207baa29dd445d141 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Thu, 7 Jul 2022 18:32:48 +0200 Subject: Avoid std::derived_from and std::bind_front Apple Clang doesn't have those yet. --- lib/events/event.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/events/event.h') diff --git a/lib/events/event.h b/lib/events/event.h index a966e613..05eb51e9 100644 --- a/lib/events/event.h +++ b/lib/events/event.h @@ -344,7 +344,7 @@ inline auto eventCast(const BasePtrT& eptr) namespace _impl { template concept Invocable_With_Downcast = - std::derived_from>, BaseT>; + std::is_base_of_v>>; } template -- cgit v1.2.3