Skip to content

Commit

Permalink
Merge pull request #123 from elbeno/speed-up-tuple
Browse files Browse the repository at this point in the history
⚡ Use `__type_pack_element` to speed up tuple indexing
  • Loading branch information
lukevalenty authored Jul 2, 2024
2 parents f02d50d + 95d8b98 commit 060e858
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 15 deletions.
35 changes: 27 additions & 8 deletions include/stdx/tuple.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ struct element<Index, T, Ts...> {
using type = T;
#else
constexpr static auto ugly_Value(index_constant<Index>) -> T;
#endif

[[nodiscard]] constexpr auto ugly_iGet_clvr(
index_constant<Index>) const & noexcept LIFETIMEBOUND -> T const & {
Expand All @@ -80,6 +79,7 @@ struct element<Index, T, Ts...> {
ugly_iGet_rvr(index_constant<Index>) && noexcept LIFETIMEBOUND -> T && {
return std::forward<T>(value);
}
#endif

template <typename U>
requires(std::same_as<U, T> or ... or std::same_as<U, Ts>)
Expand Down Expand Up @@ -123,7 +123,6 @@ struct element<Index, T, Ts...> : T {
using type = T;
#else
constexpr static auto ugly_Value(index_constant<Index>) -> T;
#endif

[[nodiscard]] constexpr auto
ugly_iGet_clvr(index_constant<Index>) const & noexcept -> T const & {
Expand All @@ -137,6 +136,7 @@ struct element<Index, T, Ts...> : T {
ugly_iGet_rvr(index_constant<Index>) && noexcept -> T && {
return std::move(*this);
}
#endif

template <typename U>
requires(std::is_same_v<U, T> or ... or std::is_same_v<U, Ts>)
Expand Down Expand Up @@ -229,9 +229,6 @@ struct tuple_impl<std::index_sequence<Is...>, index_function_list<Fs...>, Ts...>
using common_tuple_comparable = void;
using is_tuple = void;

using base_t<Is, Ts>::ugly_iGet_clvr...;
using base_t<Is, Ts>::ugly_iGet_lvr...;
using base_t<Is, Ts>::ugly_iGet_rvr...;
using base_t<Is, Ts>::ugly_tGet_clvr...;
using base_t<Is, Ts>::ugly_tGet_lvr...;
using base_t<Is, Ts>::ugly_tGet_rvr...;
Expand All @@ -243,6 +240,10 @@ struct tuple_impl<std::index_sequence<Is...>, index_function_list<Fs...>, Ts...>
constexpr static auto ugly_Value(...) -> void;
using base_t<Is, Ts>::ugly_Value...;
template <std::size_t I> using element_t = decltype(ugly_Value(index<I>));

using base_t<Is, Ts>::ugly_iGet_clvr...;
using base_t<Is, Ts>::ugly_iGet_lvr...;
using base_t<Is, Ts>::ugly_iGet_rvr...;
#endif

template <typename Init, typename Op>
Expand Down Expand Up @@ -274,30 +275,48 @@ struct tuple_impl<std::index_sequence<Is...>, index_function_list<Fs...>, Ts...>
}

template <std::size_t I>
[[nodiscard]] constexpr auto operator[](index_constant<I> i) const
[[nodiscard]] constexpr auto
operator[]([[maybe_unused]] index_constant<I> i) const
& LIFETIMEBOUND->decltype(auto) {
if constexpr (I >= sizeof...(Ts)) {
error::index_out_of_bounds<I, Ts...>();
} else {
#if __has_builtin(__type_pack_element)
using B = base_t<I, __type_pack_element<I, Ts...>>;
return this->B::ugly_Value_clvr();
#else
return this->ugly_iGet_clvr(i);
#endif
}
}
template <std::size_t I>
[[nodiscard]] constexpr auto operator[](index_constant<I> i) &
[[nodiscard]] constexpr auto
operator[]([[maybe_unused]] index_constant<I> i) &
LIFETIMEBOUND->decltype(auto) {
if constexpr (I >= sizeof...(Ts)) {
error::index_out_of_bounds<I, Ts...>();
} else {
#if __has_builtin(__type_pack_element)
using B = base_t<I, __type_pack_element<I, Ts...>>;
return this->B::ugly_Value_lvr();
#else
return this->ugly_iGet_lvr(i);
#endif
}
}
template <std::size_t I>
[[nodiscard]] constexpr auto operator[](index_constant<I> i) &&
[[nodiscard]] constexpr auto
operator[]([[maybe_unused]] index_constant<I> i) &&
LIFETIMEBOUND->decltype(auto) {
if constexpr (I >= sizeof...(Ts)) {
error::index_out_of_bounds<I, Ts...>();
} else {
#if __has_builtin(__type_pack_element)
using B [[maybe_unused]] = base_t<I, __type_pack_element<I, Ts...>>;
return std::move(*this).B::ugly_Value_rvr();
#else
return std::move(*this).ugly_iGet_rvr(i);
#endif
}
}

Expand Down
12 changes: 5 additions & 7 deletions include/stdx/tuple_algorithms.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,11 @@ template <tuplelike... Ts> [[nodiscard]] constexpr auto tuple_cat(Ts &&...ts) {
return [&]<std::size_t... Is>(std::index_sequence<Is...>) {
using T = stdx::tuple<stdx::tuple_element_t<
element_indices[Is].inner,
std::remove_cvref_t<
decltype(std::move(outer_tuple)
.ugly_iGet_rvr(
index<element_indices[Is].outer>))>>...>;
return T{std::move(outer_tuple)
.ugly_iGet_rvr(index<element_indices[Is].outer>)
[index<element_indices[Is].inner>]...};
std::remove_cvref_t<decltype(std::move(
outer_tuple)[index<element_indices[Is].outer>])>>...>;
return T{
std::move(outer_tuple)[index<element_indices[Is].outer>]
[index<element_indices[Is].inner>]...};
}(std::make_index_sequence<total_num_elements>{});
}
}
Expand Down

0 comments on commit 060e858

Please sign in to comment.