diff --git a/test/initial_draft.cpp b/test/initial_draft.cpp index c7eb283..339ea8a 100644 --- a/test/initial_draft.cpp +++ b/test/initial_draft.cpp @@ -13,6 +13,8 @@ #include #include +#define STLAB_FWD(x) std::forward(x) + /* If exception inside of a segment _apply_ function throws an exception then the exception must be @@ -92,6 +94,17 @@ class segment { } }; +namespace detail { + +/// Apply a recursive lambda to each element in the tuple-like Segments. +template +constexpr auto fold_over(Fold fold, Segments&& segments) { + return std::apply([fold](auto&&... links) { return fold(fold, STLAB_FWD(links)...); }, + STLAB_FWD(segments)); +} + +} // namespace detail + template using segment_result_type = decltype(std::declval().result_type_helper(std::declval()...)); @@ -100,65 +113,54 @@ using segment_result_type = simplify this code by handing the multi-argument case earlier (somehow). */ -#define STLAB_FWD(x) std::forward(x) - template class chain { Tail _tail; segment _head; - /// Apply a recursive lambda to each element in _tail, followed by _head. - template - auto fold_over(F fold) && { - return std::apply([fold](auto&&... links) { return fold(fold, STLAB_FWD(links)...); }, - std::tuple_cat(std::move(_tail), std::tuple(std::move(_head)))); - } - - template - static consteval auto static_fold_over(F fold) { - return std::apply([fold](auto&&... links) { return fold(fold, STLAB_FWD(links)...); }, - std::tuple_cat(std::declval(), - std::tuple(std::declval>()))); - } - /// Return a lambda with the signature of /// head( tail( tail<1>( tail<0>( auto&& args... ) ) ) ) /// for computing the result type of this chain. - static consteval auto result_type_helper() { - return static_fold_over([](auto fold, auto&& first, auto&&... rest) { - if constexpr (sizeof...(rest) == 0) { - return [_segment = STLAB_FWD(first)](auto&&... args) mutable { - return std::move(_segment).result_type_helper(STLAB_FWD(args)...); - }; - } else { - return [_segment = STLAB_FWD(first).append(fold(fold, STLAB_FWD(rest)...))]( - auto&&... args) mutable { - return std::move(_segment).result_type_helper(STLAB_FWD(args)...); - }; - } - }); + static consteval auto result_type_helper(Tail&& tail, segment&& head) { + return detail::fold_over( + [](auto fold, auto&& first, auto&&... rest) { + if constexpr (sizeof...(rest) == 0) { + return [_segment = STLAB_FWD(first)](auto&&... args) mutable { + return std::move(_segment).result_type_helper(STLAB_FWD(args)...); + }; + } else { + return [_segment = STLAB_FWD(first).append(fold(fold, STLAB_FWD(rest)...))]( + auto&&... args) mutable { + return std::move(_segment).result_type_helper(STLAB_FWD(args)...); + }; + } + }, + std::tuple_cat(std::move(tail), std::tuple{std::move(head)})); } template auto expand(const R& receiver) && { - return std::move(*this).fold_over([receiver](auto fold, auto&& first, auto&&... rest) { - if constexpr (sizeof...(rest) == 0) { - return [receiver, - _segment = STLAB_FWD(first).append(receiver)](auto&&... args) mutable { - return std::move(_segment).invoke(receiver, STLAB_FWD(args)...); - }; - } else { - return [receiver, _segment = STLAB_FWD(first).append( - fold(fold, STLAB_FWD(rest)...))](auto&&... args) mutable { - return std::move(_segment).invoke(receiver, STLAB_FWD(args)...); - }; - } - }); + return detail::fold_over( + [receiver](auto fold, auto&& first, auto&&... rest) { + if constexpr (sizeof...(rest) == 0) { + return [receiver, + _segment = STLAB_FWD(first).append(receiver)](auto&&... args) mutable { + return std::move(_segment).invoke(receiver, STLAB_FWD(args)...); + }; + } else { + return [receiver, _segment = STLAB_FWD(first).append( + fold(fold, STLAB_FWD(rest)...))](auto&&... args) mutable { + return std::move(_segment).invoke(receiver, STLAB_FWD(args)...); + }; + } + }, + std::tuple_cat(std::move(_tail), std::tuple{std::move(_head)})); } public: template - using result_type = decltype(result_type_helper()(std::declval()...)); + using result_type = decltype(result_type_helper( + std::declval(), std::declval>())(std::declval()...)); explicit chain(Tail&& tail, segment&& head) : _tail{std::move(tail)}, _head{std::move(head)} {}