Implement react::map(func, vector)

This commit is contained in:
Nikita Lisitsa 2023-04-21 17:26:19 +03:00
parent 343cb394b5
commit d2afa09adf

View file

@ -2,6 +2,8 @@
#include <psemek/react/value.hpp>
#include <vector>
namespace psemek::react
{
@ -11,7 +13,7 @@ namespace psemek::react
template <typename F, typename ... Args>
auto map_impl(F func, value<Args> ... args)
{
using R = decltype(func(std::declval<Args const &>()...));
using R = std::decay_t<decltype(func(std::declval<Args const &>()...))>;
auto node = std::make_shared<detail::node<R>>();
auto weak_node = std::weak_ptr{node};
@ -46,6 +48,57 @@ namespace psemek::react
return value<R>(detail::internal_tag{}, std::move(node));
}
template <typename F, typename T>
auto map_impl(F func, std::vector<value<T>> args)
{
using R = std::decay_t<decltype(func(std::declval<std::vector<T>>()))>;
auto node = std::make_shared<detail::node<R>>();
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<util::signal<void>::subscription_token> internal_tokens;
std::vector<typename util::signal<T>::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<T> 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<R>(detail::internal_tag{}, std::move(node));
}
}
template <typename F, typename ... Args>
@ -54,4 +107,16 @@ namespace psemek::react
return detail::map_impl(std::move(func), make_value(std::forward<Args>(args))...);
}
template <typename F, typename T>
auto map(F func, std::vector<value<T>> args)
{
return detail::map_impl(std::move(func), std::move(args));
}
template <typename T>
value<std::vector<T>> unpack(std::vector<value<T>> args)
{
return map([](std::vector<T> x) -> std::vector<T> { return x; }, std::move(args));
}
}