From acc632ac793907417aba6bb9ddd2054081719f07 Mon Sep 17 00:00:00 2001 From: Dmitry Kazakov Date: Thu, 13 Oct 2022 15:49:54 +0300 Subject: [PATCH] Test implementation of deferred calculation of the 'get()' part of lenses WARNING: this patch is only a proof of concept. It breaks a lot of unittests and I don't know how to fix them. The perpose of this patch is twofold: 1) Avoid execution of the 'get()' part fo the lens when only set is requested 2) Avoid double expiring of the object when 'get()' part of the lens accepts the "whole" object as a non-reference --- lager/detail/lens_nodes.hpp | 22 ++++++++++++---------- lager/lenses.hpp | 7 ++++--- lager/util.hpp | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/lager/detail/lens_nodes.hpp b/lager/detail/lens_nodes.hpp index 51a791b0..bf270ef6 100644 --- a/lager/detail/lens_nodes.hpp +++ b/lager/detail/lens_nodes.hpp @@ -36,18 +36,20 @@ class lens_reader_node; template class Base> class lens_reader_node, Base> : public inner_node< - std::decay_t(), - zug::tuplify(std::declval>()...)))>, + std::decay_t< + remove_deferred_t< + decltype(view(std::declval(), + zug::tuplify(std::declval>()...)))>>, zug::meta::pack, Base> { using base_t = inner_node< - std::decay_t(), - zug::tuplify(std::declval>()...)))>, - zug::meta::pack, - Base>; + std::decay_t< + remove_deferred_t< + decltype(view(std::declval(), + zug::tuplify(std::declval>()...)))>>, + zug::meta::pack, + Base>; protected: Lens lens_; @@ -55,14 +57,14 @@ class lens_reader_node, Base> public: template lens_reader_node(Lens2&& l, ParentsTuple&& parents) - : base_t{view(l, current_from(parents)), + : base_t{static_cast(view(l, current_from(parents))), std::forward(parents)} , lens_{std::forward(l)} {} void recompute() final { - this->push_down(view(lens_, current_from(this->parents()))); + this->push_down(static_cast(view(lens_, current_from(this->parents())))); } }; diff --git a/lager/lenses.hpp b/lager/lenses.hpp index 1f8db7c6..79d8129d 100644 --- a/lager/lenses.hpp +++ b/lager/lenses.hpp @@ -107,9 +107,10 @@ auto getset(Getter&& getter, Setter&& setter) { return zug::comp([=](auto&& f) { return [&, f = LAGER_FWD(f)](auto&& p) { - return f(getter(std::forward(p)))([&](auto&& x) { - return setter(std::forward(p), - std::forward(x)); + return f(lager::make_deferred(getter, std::forward(p))) + ([&](auto&& x) { + return setter(std::forward(p), + std::forward(x)); }); }; }); diff --git a/lager/util.hpp b/lager/util.hpp index d601c79f..cf84c6fb 100644 --- a/lager/util.hpp +++ b/lager/util.hpp @@ -115,4 +115,40 @@ const T& unwrap(const T& x) return x; } +/*! + * Defers calculation of the value of the function till type + * conversion is actually requested + */ + +template +struct deferred +{ + Func &&func; + P &&p; + + operator X() { + return LAGER_FWD(std::forward(func)(std::forward

(p))); + } +}; + +template ()(std::declval

()))> +auto make_deferred(Func&& f, P&& p) -> deferred +{ + return {std::forward(f), std::forward

(p)}; +} + +template +struct remove_deferred { + using type = T; +}; + +template +struct remove_deferred> { + using type = X; +}; + +template +using remove_deferred_t = typename remove_deferred::type; + + } // namespace lager