diff --git a/include/continuable/detail/composition-remapping.hpp b/include/continuable/detail/composition-remapping.hpp index 3ac5eb6..afd68cb 100644 --- a/include/continuable/detail/composition-remapping.hpp +++ b/include/continuable/detail/composition-remapping.hpp @@ -31,13 +31,14 @@ #ifndef CONTINUABLE_DETAIL_COMPOSITION_REMAPPING_HPP_INCLUDED #define CONTINUABLE_DETAIL_COMPOSITION_REMAPPING_HPP_INCLUDED +#include #include #include #include #include #include -#include +#include #include namespace cti { @@ -54,6 +55,24 @@ namespace composition { /// - single async value -> single value /// - multiple async value -> tuple of async values. namespace remapping { +/// Guards a type to be default constructible, +/// and wraps it into an optional type if it isn't default constructible. +template +using lazy_value_t = std::conditional_t::value, + T, container::flat_variant>; + +template +decltype(auto) unpack_lazy(T&& value) { + return std::forward(value); +} +template +T&& unpack_lazy(container::flat_variant&& value) { + assert(value.template is() && + "The composition was finalized before all values were present!"); + + return std::move(value.template cast()); +} + template class continuable_box; template @@ -83,7 +102,7 @@ class continuable_box< continuable_base>> { continuable_base> continuable_; - First first_; + lazy_value_t first_; public: explicit continuable_box( @@ -100,7 +119,7 @@ public: } auto unbox() && { - return std::move(first_); + return unpack_lazy(std::move(first_)); } }; template @@ -109,7 +128,7 @@ class continuable_box< continuable_base> continuable_; - std::tuple args_; + lazy_value_t> args_; public: explicit continuable_box( @@ -130,7 +149,7 @@ public: } auto unbox() && { - return traits::unpack(std::move(args_), [](auto&&... args) { + return traits::unpack(unpack_lazy(std::move(args_)), [](auto&&... args) { return spread_this(std::forward(args)...); }); }