From d2afa09adf3af9e7f28dd320e12300707070378a Mon Sep 17 00:00:00 2001 From: lisyarus Date: Fri, 21 Apr 2023 17:26:19 +0300 Subject: [PATCH] Implement react::map(func, vector) --- libs/react/include/psemek/react/map.hpp | 67 ++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/libs/react/include/psemek/react/map.hpp b/libs/react/include/psemek/react/map.hpp index e6fc3945..44a9f716 100644 --- a/libs/react/include/psemek/react/map.hpp +++ b/libs/react/include/psemek/react/map.hpp @@ -2,6 +2,8 @@ #include +#include + namespace psemek::react { @@ -11,7 +13,7 @@ namespace psemek::react template auto map_impl(F func, value ... args) { - using R = decltype(func(std::declval()...)); + using R = std::decay_t()...))>; auto node = std::make_shared>(); auto weak_node = std::weak_ptr{node}; @@ -46,6 +48,57 @@ namespace psemek::react return value(detail::internal_tag{}, std::move(node)); } + template + auto map_impl(F func, std::vector> args) + { + using R = std::decay_t>()))>; + + auto node = std::make_shared>(); + auto weak_node = std::weak_ptr{node}; + + auto internal_subscriber = [weak_node]{ + if (auto node = weak_node.lock()) + { + node->cached_value = std::nullopt; + node->internal_signal(); + } + }; + + auto external_subscriber = [weak_node](auto const &){ + if (auto node = weak_node.lock()) + { + if (!node->cached_value) + node->external_signal(node->value()); + } + }; + + std::vector::subscription_token> internal_tokens; + std::vector::subscription_token> external_tokens; + + internal_tokens.reserve(args.size()); + external_tokens.reserve(args.size()); + + for (auto const & arg : args) + { + internal_tokens.push_back(arg.subscribe(detail::internal_tag{}, internal_subscriber)); + external_tokens.push_back(arg.subscribe(external_subscriber)); + } + + node->getter = [ + func = std::move(func), + internal_tokens = std::move(internal_tokens), + external_tokens = std::move(external_tokens), + args = std::move(args)]() -> R { + std::vector arg_values; + arg_values.reserve(args.size()); + for (auto const & arg : args) + arg_values.push_back(*arg); + return func(std::move(arg_values)); + }; + + return value(detail::internal_tag{}, std::move(node)); + } + } template @@ -54,4 +107,16 @@ namespace psemek::react return detail::map_impl(std::move(func), make_value(std::forward(args))...); } + template + auto map(F func, std::vector> args) + { + return detail::map_impl(std::move(func), std::move(args)); + } + + template + value> unpack(std::vector> args) + { + return map([](std::vector x) -> std::vector { return x; }, std::move(args)); + } + }