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