#pragma once #if __cplusplus >= 202002L #include #include #include #include #include #include namespace stdx { inline namespace v1 { template using index_constant = std::integral_constant; template constexpr static index_constant index{}; inline namespace literals { template CONSTEVAL auto operator""_idx() { return index()>; } } // namespace literals template struct tag_constant; template constexpr static tag_constant *tag{}; namespace error { template constexpr auto always_false_v = false; template struct type_from_tag_constant { using type = T; }; template struct type_from_tag_constant *> { using type = T; }; template struct looking_for; template struct in_tuple; template struct index; template struct max_index; template constexpr auto type_not_found() { using type = typename type_from_tag_constant::type; static_assert(always_false_v, in_tuple>, "Type not found in tuple!"); } template constexpr auto index_out_of_bounds() { static_assert( always_false_v, max_index, in_tuple>, "Tuple index out of bounds!"); } } // namespace error namespace detail { template struct element { #if __has_builtin(__type_pack_element) using type = T; #else constexpr static auto ugly_Value(index_constant) -> T; [[nodiscard]] constexpr auto ugly_iGet_clvr( index_constant) const & noexcept LIFETIMEBOUND -> T const & { return value; } [[nodiscard]] constexpr auto ugly_iGet_lvr(index_constant) & noexcept LIFETIMEBOUND -> T & { return value; } [[nodiscard]] constexpr auto ugly_iGet_rvr(index_constant) && noexcept LIFETIMEBOUND -> T && { return std::forward(value); } #endif template requires(std::same_as or ... or std::same_as) [[nodiscard]] constexpr auto ugly_tGet_clvr( tag_constant *) const & noexcept LIFETIMEBOUND -> T const & { return value; } template requires(std::same_as or ... or std::same_as) [[nodiscard]] constexpr auto ugly_tGet_lvr(tag_constant *) & noexcept LIFETIMEBOUND -> T & { return value; } template requires(std::same_as or ... or std::same_as) [[nodiscard]] constexpr auto ugly_tGet_rvr(tag_constant *) && noexcept LIFETIMEBOUND -> T && { return std::forward(value); } constexpr auto ugly_Value_clvr() const & LIFETIMEBOUND -> T const & { return value; } constexpr auto ugly_Value_lvr() & LIFETIMEBOUND -> T & { return value; } constexpr auto ugly_Value_rvr() && LIFETIMEBOUND -> T && { return std::forward(value); } T value; private: [[nodiscard]] friend constexpr auto operator==(element const &, element const &) -> bool = default; [[nodiscard]] friend constexpr auto operator<=>(element const &, element const &) = default; }; template struct fold_helper { Op op; Value value; private: template [[nodiscard]] friend constexpr auto operator+(fold_helper &&lhs, Rhs &&rhs) { using R = decltype(lhs.op(std::move(lhs).value, std::forward(rhs))); return fold_helper>{ lhs.op, lhs.op(std::move(lhs).value, std::forward(rhs))}; } template [[nodiscard]] friend constexpr auto operator+(Lhs &&lhs, fold_helper &&rhs) { using R = decltype(rhs.op(std::forward(lhs), std::move(rhs).value)); return fold_helper>{ rhs.op, rhs.op(std::forward(lhs), std::move(rhs).value)}; } }; template fold_helper(Op, Value) -> fold_helper>; template struct join_helper { Op op; Value value; }; template join_helper(Op, Value) -> join_helper>; // Note: operator+ is not a hidden friend of join_helper to avoid template // instantiation abiguity template [[nodiscard]] constexpr auto operator+(join_helper &&lhs, join_helper &&rhs) { using R = decltype(lhs.op(std::move(lhs).value, std::move(rhs).value)); return join_helper>{ lhs.op, lhs.op(std::move(lhs).value, std::move(rhs).value)}; } template