diff --git a/include/utempl/tuple.hpp b/include/utempl/tuple.hpp index 9fa94b5..487adb0 100644 --- a/include/utempl/tuple.hpp +++ b/include/utempl/tuple.hpp @@ -23,7 +23,10 @@ struct TupleHelper, Ts...> : public TupleLeaf inline constexpr TupleHelper(TTs&&... args) : TupleLeaf{std::forward(args)}... {}; inline constexpr TupleHelper(const TupleHelper&) = default; + inline constexpr TupleHelper(TupleHelper&) = default; inline constexpr TupleHelper(TupleHelper&&) = default; + inline constexpr TupleHelper() : + TupleLeaf{}... {}; inline constexpr bool operator==(const TupleHelper&) const = default; }; @@ -64,7 +67,9 @@ struct Tuple : public impl::TupleHelper, Ts...> { impl::TupleHelper, Ts...>(std::move(args)...) {}; inline constexpr Tuple(const Tuple&) = default; inline constexpr Tuple(Tuple&&) = default; - + inline constexpr Tuple(Tuple&) = default; + inline constexpr Tuple() requires (sizeof...(Ts) != 0) : + impl::TupleHelper, Ts...>() {}; template inline constexpr bool operator==(const Tuple& other) const requires (TypeList{} == TypeList{}) { diff --git a/include/utempl/utils.hpp b/include/utempl/utils.hpp index b421b37..da223e1 100644 --- a/include/utempl/utils.hpp +++ b/include/utempl/utils.hpp @@ -111,41 +111,114 @@ inline constexpr auto Reverse(Tuple&& tuple) { }(std::make_index_sequence>()); }; +namespace impl { + +template +struct LeftFold; + +template +struct LeftFold { + T data; +}; + +template +struct LeftFold { + T data; + const F& f; + template + inline constexpr auto operator|(LeftFold&& other) { + using R = decltype(f(std::move(this->data), std::move(other.data))); + return LeftFold{.data = f(std::move(this->data), std::move(other.data)), .f = this->f}; + }; +}; + + + +} // namespace impl + + +template +inline constexpr auto LeftFold(Tuple&& tuple, T&& init, F&& f) { + return [&](std::index_sequence){ + return ( + impl::LeftFold, std::remove_cvref_t>{.data = std::forward(init), .f = std::forward(f)} + | ... + | impl::LeftFold(tuple))>>{.data = Get(tuple)} + ).data; + }(std::make_index_sequence>()); +}; + + + template inline constexpr auto TupleCat(Tuple&& tuple, Tuple2&& tuple2) { return [&](std::index_sequence, std::index_sequence){ return MakeTuple(Get(tuple)..., Get(tuple2)...); }(std::make_index_sequence>(), std::make_index_sequence>()); }; -namespace impl { -template -struct TupleCater { - Tuple tuple; - template - inline constexpr auto operator+(TupleCater&& other) { - using ResultType = decltype(TupleCat(std::move(this->tuple), other.tuple)); - return TupleCater{TupleCat(std::move(this->tuple), std::move(other.tuple))}; - }; -}; -} // namespace impl template -inline constexpr auto TupleCat(Tuples&&... tuples) { - return (impl::TupleCater{std::forward(tuples)} + ...).tuple; +inline constexpr auto TupleCat(Tuples&&... tuples) requires (sizeof...(tuples) >= 1) { + return LeftFold( + Tuple{std::forward(tuples)...}, + MakeTuple(std::forward(tuples)...))>(), + [](Tup&& tup, Tup2&& tup2){ + return TupleCat(std::forward(tup), std::forward(tup2)); + }); }; +template +inline constexpr auto Tie(Ts&... args) -> Tuple { + return {args...}; +}; + +template