diff --git a/Tutorial.md b/Tutorial.md index c9f6c22..4eb9421 100644 --- a/Tutorial.md +++ b/Tutorial.md @@ -676,6 +676,25 @@ int main(int argc, char* argv[]) zipped_tuple_map(f_, a_, b_); + luple l0; + luple l1(std::string("C++23")); + + luple l2; + + auto l3 = make_luple(j, std::string("template")); + auto l4 = luple_cat(l0, l1, l2, l3); + + using ltype = decltype(l4); + + std::cout << l4.get<0>() << std::endl; + l4.apply([](std::string, short, char, double, std::string){}); + + is_identical>(); + is_identical, 5>(); + + is_identical, std::string>(); + is_identical, double>(); + is_identical, 10>(); is_identical, std::integer_sequence>(); diff --git a/example/monster.cpp b/example/monster.cpp index f0e26b1..9547486 100644 --- a/example/monster.cpp +++ b/example/monster.cpp @@ -674,6 +674,25 @@ int main(int argc, char* argv[]) zipped_tuple_map(f_, a_, b_); + luple l0; + luple l1(std::string("C++23")); + + luple l2; + + auto l3 = make_luple(j, std::string("template")); + auto l4 = luple_cat(l0, l1, l2, l3); + + using ltype = decltype(l4); + + std::cout << l4.get<0>() << std::endl; + l4.apply([](std::string, short, char, double, std::string){}); + + is_identical>(); + is_identical, 5>(); + + is_identical, std::string>(); + is_identical, double>(); + is_identical, 10>(); is_identical, std::integer_sequence>(); diff --git a/include/monster.hpp b/include/monster.hpp index 395b1d9..8ff6753 100644 --- a/include/monster.hpp +++ b/include/monster.hpp @@ -7374,6 +7374,202 @@ namespace monster } } + template + class luple + { + public: + constexpr luple() + { + lambda([](storage&... s) + { + (..., s.init()); + }); + } + + template ()))) = nullptr> + constexpr luple(Brgs&&... brgs) + { + lambda([&](storage&... s) + { + (..., s.init(std::forward(brgs))); + }); + } + + constexpr luple(const luple& l) + { + lambda([&](storage&... s) + { + l.lambda([&](const storage&... t) + { + (..., new (s.operator->()) Args(*t)); + }); + }); + } + + constexpr luple(luple&& l) + { + lambda([&](storage&... s) + { + l.lambda([&](storage&... t) + { + (..., new (s.operator->()) Args(static_cast(*t))); + }); + }); + } + + template + constexpr decltype(auto) apply(F&& f) + { + lambda([&](const storage&... s) -> decltype(auto) + { + return std::invoke(std::forward(f), *s...); + }); + } + + template + constexpr decltype(auto) get() + { + return [&](std::index_sequence) + { + return lambda([](nil..., auto& e, auto ...) -> auto& + { + return *e; + }); + } + (std::make_index_sequence()); + } + + ~luple() + { + lambda([](storage&... s) + { + (..., s->~Args()); + }); + } + + private: + template + struct nil + { + template + nil(T&&) + { + } + }; + + template + class alignas(T) storage + { + public: + storage() = default; + + template + constexpr void init(Brgs&&... args) + { + new (reinterpret_cast(std::addressof(data))) T(std::forward(args)...); + } + + T* operator->() + { + return reinterpret_cast(std::addressof(data)); + } + + const T* operator->() const + { + return reinterpret_cast(std::addressof(data)); + } + + T& operator*() + { + return *operator->(); + } + + const T& operator*() const + { + return *operator->(); + } + + private: + char data[sizeof(T)]; + }; + + template + static constexpr decltype(auto) to_lambda(Brgs... brgs) + { + return [=](auto f) mutable -> decltype(auto) + { + return f(brgs...); + }; + } + + mutable decltype(to_lambda(storage()...)) lambda = to_lambda(storage()...); + }; + + template + luple(Args...) -> luple; + + template + luple(const luple&) -> luple; + + template + struct is_luple : std::false_type + { + }; + + template + struct is_luple> : std::true_type + { + }; + + template + inline constexpr auto is_luple_v = is_luple::value; + + template + struct luple_size; + + template + struct luple_size> : std::integral_constant + { + }; + + template + inline constexpr size_t luple_size_v = luple_size::value; + + template + struct luple_element; + + template + struct luple_element> + { + using type = std::remove_cvref_t>().template get())>; + }; + + template + using luple_element_t = typename luple_element::type; + + template + constexpr decltype(auto) make_luple(Args&&... args) + { + return luple(static_cast>(args)...); + } + + template + constexpr decltype(auto) luple_cat(Args&&... args) + { + auto t = make_luple(std::forward(args)...); + + if constexpr(!sizeof...(Args)) + return t; + else + { + return [&]