From 6d2db29fbc13ac6f58c3e554c53d88fc2a49b8bd Mon Sep 17 00:00:00 2001 From: Nana Sakisaka <1901813+saki7@users.noreply.github.com> Date: Sun, 27 Sep 2026 01:37:18 +0900 Subject: [PATCH] Improve throughput of type list related metafunctions --- include/iris/type_list.hpp | 120 +++++++++++++++++++++++++++++-------- test/type_list.cpp | 2 +- 2 files changed, 97 insertions(+), 25 deletions(-) diff --git a/include/iris/type_list.hpp b/include/iris/type_list.hpp index b4f19b5..05484e0 100644 --- a/include/iris/type_list.hpp +++ b/include/iris/type_list.hpp @@ -59,20 +59,97 @@ struct concat_type_list, type_list, Rest...> // ---------------------------------------------------------- -namespace detail { +template +struct type_bases : Ts... +{ + template class TT> + using rebind = TT; +}; template -struct identity_bases : std::type_identity... + requires (sizeof...(Ts) > 0) +struct type_bases...> : std::type_identity... { template class TT> using rebind = TT; }; +namespace detail { + +template +struct type_bases_push_back_impl; + +template +struct type_bases_push_back_impl...>, T> +{ + using type = type_bases..., std::type_identity>; +}; + +} // detail + +template +using type_bases_push_back = detail::type_bases_push_back_impl::type; + +// -------------------------------------------------- + +template +using identity_bases = type_bases...>; + template -concept identity_base_of = requires(BasesT* bases) { +concept has_identity_base = requires(BasesT* bases) { static_cast*>(bases); }; +// -------------------------------------------------- + +template +struct indexed_virtual_identity : virtual std::type_identity +{ + static void select(std::type_identity*); +}; + +template + requires (sizeof...(Ts) > 0) +struct type_bases...> : indexed_virtual_identity... +{ + template class TT> + using rebind = TT; + + using indexed_virtual_identity::select...; +}; + +template +concept has_exactly_one_identity_base = requires(std::type_identity* base) { + // If multiple bases exist, overload resolution is ambiguous + BasesT::select(base); +}; + +// -------------------------------------------------- + +namespace detail { + +template class IdentityTT, class Indexes, class... Ts> +struct indexed_identity_bases_impl; + +template class IdentityTT, std::size_t... Is, class... Ts> +struct indexed_identity_bases_impl< + IdentityTT, std::index_sequence, Ts... +> +{ + using type = type_bases...>; +}; + +} // detail + +template +using indexed_virtual_identity_bases = detail::indexed_identity_bases_impl< + indexed_virtual_identity, std::index_sequence_for, Ts... +>::type; + +// -------------------------------------------------- + +namespace detail { + template struct unique_type_list_impl; @@ -83,13 +160,13 @@ struct unique_type_list_impl }; template - requires identity_base_of + requires has_identity_base struct unique_type_list_impl : unique_type_list_impl {}; template - requires (!identity_base_of>) + requires (!has_identity_base>) struct unique_type_list_impl, T, Rest...> : unique_type_list_impl, Rest...> {}; @@ -109,7 +186,7 @@ template struct unique_type_list> { using type = detail::unique_type_list_impl< - detail::identity_bases<>, Ts... + identity_bases<>, Ts... >::type::template rebind; }; @@ -248,33 +325,28 @@ inline constexpr std::size_t find_index_v = find_index::value; template -struct is_in : std::disjunction...> {}; +struct is_in : std::bool_constant< + has_identity_base> +> +{}; template -inline constexpr bool is_in_v = is_in::value; +inline constexpr bool is_in_v = has_identity_base>; // ---------------------------------------------------------- -namespace detail { - -template -struct exactly_once_impl : std::bool_constant {}; - -template -struct exactly_once_impl - : exactly_once_impl, T, Us...> {}; - -template -struct exactly_once_impl - : std::conditional_t, std::false_type, exactly_once_impl> {}; - -} // detail - template struct exactly_once; template class TT, class... Ts> -struct exactly_once> : detail::exactly_once_impl +struct exactly_once> : std::false_type +{ + static_assert(sizeof...(Ts) > 0); +}; + +template class TT, class... Ts> + requires has_exactly_one_identity_base> +struct exactly_once> : std::true_type { static_assert(sizeof...(Ts) > 0); }; diff --git a/test/type_list.cpp b/test/type_list.cpp index 19bb5e9..9af2ff4 100644 --- a/test/type_list.cpp +++ b/test/type_list.cpp @@ -78,7 +78,7 @@ TEST_CASE("pack_indexing") TEST_CASE("exactly_once") { STATIC_CHECK(iris::exactly_once_v>); - STATIC_CHECK_FALSE(iris::exactly_once_v>); + STATIC_CHECK(!iris::exactly_once_v>); } TEST_CASE("is_in")