From 4eb10e814756020a0618b1cc0056a44a75132a0b Mon Sep 17 00:00:00 2001 From: Nana Sakisaka <1901813+saki7@users.noreply.github.com> Date: Wed, 23 Sep 2026 19:49:21 +0900 Subject: [PATCH] Split `type_list` and pack indexing to a separate header --- include/iris/alloy/adapt.hpp | 2 +- .../detail/preprocessed/tuple_impl.hpp.pre.in | 2 +- include/iris/alloy/detail/std_get.hpp | 2 +- include/iris/alloy/detail/tuple_impl.hpp | 2 +- include/iris/alloy/traits.hpp | 4 +- include/iris/alloy/utility.hpp | 2 +- include/iris/hash.hpp | 3 +- .../iris/rvariant/detail/variant_storage.hpp | 86 +++---- include/iris/rvariant/detail/visit.hpp | 19 +- include/iris/rvariant/pack.hpp | 6 +- include/iris/rvariant/rvariant.hpp | 1 + include/iris/rvariant/subset.hpp | 4 +- include/iris/rvariant/variant_helper.hpp | 3 +- include/iris/type_list.hpp | 231 ++++++++++++++++++ include/iris/type_traits.hpp | 183 +------------- include/iris/units/traits.hpp | 1 + test/CMakeLists.txt | 1 + test/core.cpp | 42 ---- test/rvariant/get_visit.cpp | 2 +- test/type_list.cpp | 68 ++++++ test/type_traits.cpp | 8 +- 21 files changed, 380 insertions(+), 292 deletions(-) create mode 100644 include/iris/type_list.hpp create mode 100644 test/type_list.cpp diff --git a/include/iris/alloy/adapt.hpp b/include/iris/alloy/adapt.hpp index f4f7031..2dfde30 100644 --- a/include/iris/alloy/adapt.hpp +++ b/include/iris/alloy/adapt.hpp @@ -5,7 +5,7 @@ #include // IWYU pragma: keep -#include // IWYU pragma: keep +#include // IWYU pragma: keep #include #include diff --git a/include/iris/alloy/detail/preprocessed/tuple_impl.hpp.pre.in b/include/iris/alloy/detail/preprocessed/tuple_impl.hpp.pre.in index 2c723e5..347f65e 100644 --- a/include/iris/alloy/detail/preprocessed/tuple_impl.hpp.pre.in +++ b/include/iris/alloy/detail/preprocessed/tuple_impl.hpp.pre.in @@ -9,7 +9,7 @@ #include -#include +#include #include diff --git a/include/iris/alloy/detail/std_get.hpp b/include/iris/alloy/detail/std_get.hpp index cc149af..d571087 100644 --- a/include/iris/alloy/detail/std_get.hpp +++ b/include/iris/alloy/detail/std_get.hpp @@ -5,7 +5,7 @@ #include // IWYU pragma: keep -#include +#include #include diff --git a/include/iris/alloy/detail/tuple_impl.hpp b/include/iris/alloy/detail/tuple_impl.hpp index 4100180..1624c89 100644 --- a/include/iris/alloy/detail/tuple_impl.hpp +++ b/include/iris/alloy/detail/tuple_impl.hpp @@ -11,7 +11,7 @@ #include -#include +#include #include diff --git a/include/iris/alloy/traits.hpp b/include/iris/alloy/traits.hpp index 3e66e42..3d9a379 100644 --- a/include/iris/alloy/traits.hpp +++ b/include/iris/alloy/traits.hpp @@ -7,12 +7,12 @@ #include -#include +#include #include #include -#include +#include // IWYU pragma: keep namespace iris::alloy { diff --git a/include/iris/alloy/utility.hpp b/include/iris/alloy/utility.hpp index d757202..8d4a284 100644 --- a/include/iris/alloy/utility.hpp +++ b/include/iris/alloy/utility.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include // std::invoke #include diff --git a/include/iris/hash.hpp b/include/iris/hash.hpp index 30ce008..ad9cead 100644 --- a/include/iris/hash.hpp +++ b/include/iris/hash.hpp @@ -6,7 +6,8 @@ #include // IWYU pragma: keep #include -#include +#include +#include #include #include diff --git a/include/iris/rvariant/detail/variant_storage.hpp b/include/iris/rvariant/detail/variant_storage.hpp index 04874f3..dc89dab 100644 --- a/include/iris/rvariant/detail/variant_storage.hpp +++ b/include/iris/rvariant/detail/variant_storage.hpp @@ -9,10 +9,10 @@ #include -#include +#include +#include #include -#include #include // IWYU pragma: keep @@ -79,7 +79,7 @@ template // => valueless iff move constructor throws // // Emplace (if VT(Args...) is throwing) -// rvariant tmp(std::in_place_index, std::forward(args)...); +// rvariant tmp(std::in_place_index, static_cast(args)...); // *this = std::move(tmp); // ^^^ needs to be NOT observable on user's part, as per "Effects" https://eel.is/c++draft/variant.mod#7 // ^^^^^^^^^^^^^^ @@ -193,7 +193,7 @@ IRIS_RVARIANT_ALWAYS_THROWING_UNREACHABLE_BEGIN requires std::is_constructible_v // required for not confusing some compilers constexpr explicit variadic_union(std::in_place_index_t<0>, Args&&... args) noexcept(std::is_nothrow_constructible_v) - : first(std::forward(args)...) // value-initialize; https://eel.is/c++draft/variant.ctor#3 + : first(static_cast(args)...) // value-initialize; https://eel.is/c++draft/variant.ctor#3 {} IRIS_RVARIANT_ALWAYS_THROWING_UNREACHABLE_END @@ -203,7 +203,7 @@ IRIS_RVARIANT_ALWAYS_THROWING_UNREACHABLE_END std::is_constructible_v constexpr explicit variadic_union(std::in_place_index_t, Args&&... args) noexcept(std::is_nothrow_constructible_v) - : rest(std::in_place_index, std::forward(args)...) + : rest(std::in_place_index, static_cast(args)...) {} union { @@ -245,7 +245,7 @@ IRIS_RVARIANT_ALWAYS_THROWING_UNREACHABLE_BEGIN requires std::is_constructible_v // required for not confusing some compilers constexpr explicit variadic_union(std::in_place_index_t<0>, Args&&... args) noexcept(std::is_nothrow_constructible_v) - : first(std::forward(args)...) // value-initialize; https://eel.is/c++draft/variant.ctor#3 + : first(static_cast(args)...) // value-initialize; https://eel.is/c++draft/variant.ctor#3 {} IRIS_RVARIANT_ALWAYS_THROWING_UNREACHABLE_END @@ -255,7 +255,7 @@ IRIS_RVARIANT_ALWAYS_THROWING_UNREACHABLE_END std::is_constructible_v constexpr explicit variadic_union(std::in_place_index_t, Args&&... args) noexcept(std::is_nothrow_constructible_v) - : rest(std::in_place_index, std::forward(args)...) + : rest(std::in_place_index, static_cast(args)...) {} union { @@ -281,56 +281,56 @@ template [[nodiscard]] IRIS_FORCEINLINE constexpr forward_storage_t&& forward_storage(std::remove_reference_t& v IRIS_LIFETIMEBOUND) noexcept { - return std::forward(v).storage(); + return static_cast(v).storage(); } template [[nodiscard]] IRIS_FORCEINLINE constexpr forward_storage_t&& forward_storage(std::remove_reference_t&& v IRIS_LIFETIMEBOUND) noexcept // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved) { - return std::forward(v).storage(); + return static_cast(v).storage(); } template [[nodiscard]] IRIS_FORCEINLINE constexpr auto&& raw_get(Storage&& storage IRIS_LIFETIMEBOUND) noexcept { - if constexpr (I == 0) return std::forward(storage).first; - else if constexpr (I == 1) return std::forward(storage).rest.first; - else if constexpr (I == 2) return std::forward(storage).rest.rest.first; - else if constexpr (I == 3) return std::forward(storage).rest.rest.rest.first; - else if constexpr (I == 4) return std::forward(storage).rest.rest.rest.rest.first; - else if constexpr (I == 5) return std::forward(storage).rest.rest.rest.rest.rest.first; - else if constexpr (I == 6) return std::forward(storage).rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 7) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 8) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 9) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 10) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 11) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 12) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 13) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 14) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 15) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 16) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 17) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 18) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 19) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 20) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 21) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 22) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 23) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 24) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 25) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 26) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 27) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 28) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 29) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 30) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; - else if constexpr (I == 31) return std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + if constexpr (I == 0) return static_cast(storage).first; + else if constexpr (I == 1) return static_cast(storage).rest.first; + else if constexpr (I == 2) return static_cast(storage).rest.rest.first; + else if constexpr (I == 3) return static_cast(storage).rest.rest.rest.first; + else if constexpr (I == 4) return static_cast(storage).rest.rest.rest.rest.first; + else if constexpr (I == 5) return static_cast(storage).rest.rest.rest.rest.rest.first; + else if constexpr (I == 6) return static_cast(storage).rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 7) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 8) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 9) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 10) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 11) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 12) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 13) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 14) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 15) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 16) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 17) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 18) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 19) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 20) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 21) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 22) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 23) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 24) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 25) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 26) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 27) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 28) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 29) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 30) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; + else if constexpr (I == 31) return static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.first; else if constexpr (I < 64) return detail::raw_get( - std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest); + static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest); else return detail::raw_get( - std::forward(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest + static_cast(storage).rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest .rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest.rest); } diff --git a/include/iris/rvariant/detail/visit.hpp b/include/iris/rvariant/detail/visit.hpp index 41a2f38..b003d53 100644 --- a/include/iris/rvariant/detail/visit.hpp +++ b/include/iris/rvariant/detail/visit.hpp @@ -12,6 +12,7 @@ #include #include +#include #include #include // std::bad_variant_access @@ -108,11 +109,11 @@ do_raw_visit(Visitor&& vis, Storage&& storage) // NOLINT(cppcoreguidelines-rval noexcept(raw_visit_noexcept::value) { if constexpr (!std::remove_cvref_t::never_valueless && I == 0) { - return std::forward(vis)(std::in_place_index, std::forward(storage)); + return static_cast(vis)(std::in_place_index, static_cast(storage)); } else { constexpr std::size_t RealI = valueless_unbias(I); - return std::forward(vis)(std::in_place_index, raw_get(std::forward(storage))); + return static_cast(vis)(std::in_place_index, detail::raw_get(static_cast(storage))); } } @@ -170,7 +171,7 @@ struct raw_visit_dispatch { constexpr auto const& table = raw_visit_table::table; auto const& f = table[i]; - return f(std::forward(vis), std::forward(storage)); + return f(static_cast(vis), static_cast(storage)); } }; @@ -247,7 +248,7 @@ raw_visit(Variant&& v, Visitor&& vis) // NOLINT(cppcoreguidelines-missing-std-f N, Visitor, forward_storage_t >( detail::valueless_bias(v.index_), - std::forward(vis), + static_cast(vis), detail::forward_storage(v) ); } @@ -262,7 +263,7 @@ raw_visit_i(std::size_t const biased_i, Variant&& v, Visitor&& vis) // NOLINT(c N, Visitor, forward_storage_t >( biased_i, - std::forward(vis), + static_cast(vis), detail::forward_storage(v) ); } @@ -415,9 +416,9 @@ struct multi_visitor> } else { return std::invoke_r( - std::forward(vis), + static_cast(vis), unwrap_recursive( - raw_get(Is)>(std::forward(storage)) + detail::raw_get(Is)>(static_cast(storage)) )... ); } @@ -455,7 +456,7 @@ struct visit_dispatch<-1> { constexpr auto const& table = visit_table::table; auto const& f = table[flat_i]; - return f(std::forward(vis), std::forward(storage)...); + return f(static_cast(vis), static_cast(storage)...); } }; @@ -587,7 +588,7 @@ struct visit_impl< return visit_dispatch>::template apply< R, OverloadSeq, Visitor, forward_storage_t>... >( - flat_i, std::forward(vis), forward_storage>(vars)... + flat_i, static_cast(vis), detail::forward_storage>(vars)... ); } }; diff --git a/include/iris/rvariant/pack.hpp b/include/iris/rvariant/pack.hpp index 5640bd3..db8b2fe 100644 --- a/include/iris/rvariant/pack.hpp +++ b/include/iris/rvariant/pack.hpp @@ -7,7 +7,9 @@ // Utilities related to [rvariant.pack] -#include +#include + +#include namespace iris { @@ -25,7 +27,7 @@ struct pack_union_impl> template class TT, class... Ts, class U, class... Us> struct pack_union_impl, U, Us...> : std::conditional_t< - is_in_v, + is_in_v, pack_union_impl, Us...>, pack_union_impl, Us...> > diff --git a/include/iris/rvariant/rvariant.hpp b/include/iris/rvariant/rvariant.hpp index 1de4e30..44e67de 100644 --- a/include/iris/rvariant/rvariant.hpp +++ b/include/iris/rvariant/rvariant.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include diff --git a/include/iris/rvariant/subset.hpp b/include/iris/rvariant/subset.hpp index 758e4f5..d86dc04 100644 --- a/include/iris/rvariant/subset.hpp +++ b/include/iris/rvariant/subset.hpp @@ -7,7 +7,9 @@ #include #include -#include +#include + +#include #include diff --git a/include/iris/rvariant/variant_helper.hpp b/include/iris/rvariant/variant_helper.hpp index 4baa6e6..7267371 100644 --- a/include/iris/rvariant/variant_helper.hpp +++ b/include/iris/rvariant/variant_helper.hpp @@ -12,7 +12,8 @@ #include // IWYU pragma: keep #include -#include +#include +#include #include #include diff --git a/include/iris/type_list.hpp b/include/iris/type_list.hpp new file mode 100644 index 0000000..e495b69 --- /dev/null +++ b/include/iris/type_list.hpp @@ -0,0 +1,231 @@ +#ifndef IRIS_ZZ_TYPE_LIST_HPP +#define IRIS_ZZ_TYPE_LIST_HPP + +// SPDX-License-Identifier: MIT + +#include // IWYU pragma: keep + +#include +#include + +#include // IWYU pragma: keep + +namespace iris { + +template +struct type_list +{ + static constexpr std::size_t size = sizeof...(Ts); +}; + +template +struct constant_list +{ + static constexpr std::size_t size = sizeof...(Vals); +}; + +// ---------------------------------------------------------- + +template +struct concat_type_list; + +// `concat_type_list_t` is intentionally not defined; typical use case +// of concatenating type lists involves deep recursive instantiation of +// parent templates, which sometimes makes IDE's completion choke on +// single additional type alias of `_t`. Just use `typename ...::type`. + +template<> +struct concat_type_list<> +{ + using type = type_list<>; +}; + +template +struct concat_type_list> +{ + using type = type_list; +}; + +template +struct concat_type_list, type_list> +{ + using type = type_list; +}; + +template +struct concat_type_list, type_list, Rest...> + : concat_type_list, Rest...> +{}; + +// ---------------------------------------------------------- + +namespace detail { + +template +struct do_pack_indexing; + +template +struct do_pack_indexing> +{ + template + static std::type_identity select( + // ReSharper disable once CppCStyleCast + decltype((void*)Voids)..., + std::type_identity*, + ... + ); +}; + +template +struct do_cpack_indexing; + +template +struct do_cpack_indexing> +{ + template + static std::integral_constant select( + // ReSharper disable once CppCStyleCast + decltype((void*)Voids)..., + std::integral_constant*, + ... + ); +}; + +} // detail + + +template +struct at_c; + +template +using at_c_t = at_c::type; + +// Has native pack indexing? +// Note: GCC 15 emits "sorry, unimplemented: mangling type pack index" +#if __cpp_pack_indexing >= 202311L && \ + !(defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 15) && \ + !defined(__clang__) + +# define IRIS_PACK_INDEXING(I, Ts_ellipsis) Ts_ellipsis[I] + +template struct pack_indexing { using type = Ts...[I]; }; +template using pack_indexing_t = Ts...[I]; +template struct cpack_indexing { static constexpr auto value = Ns...[I]; }; +template constexpr auto cpack_indexing_v = Ns...[I]; + +template class TT, class... Ts> +struct at_c> +{ + using type = Ts...[I]; +}; + +// ---------------------------------------------------------- +#else // no native pack indexing +template +struct pack_indexing +{ + static_assert(I < sizeof...(Ts)); + using type = decltype(detail::do_pack_indexing>::select( + static_cast*>(nullptr)... + ))::type; +}; + +template +using pack_indexing_t = pack_indexing::type; + +# define IRIS_PACK_INDEXING(I, Ts_ellipsis) ::iris::pack_indexing_t + + +template +struct cpack_indexing +{ + static_assert(I < sizeof...(Ns)); + static constexpr auto value = decltype(detail::do_cpack_indexing>::select( + static_cast*>(nullptr)... + ))::value; +}; + +template +constexpr auto cpack_indexing_v = cpack_indexing::value; + + +template class TT, class... Ts> +struct at_c> +{ + static_assert(I < sizeof...(Ts)); + using type = decltype(detail::do_pack_indexing>::select( + static_cast*>(nullptr)... + ))::type; +}; +#endif + +// ---------------------------------------------------------- + +inline constexpr std::size_t find_npos = static_cast(-1); + +namespace detail { + +template +struct find_index_impl + : std::integral_constant +{}; + +template +struct find_index_impl + : std::conditional_t< + std::is_same_v, + std::integral_constant, + find_index_impl + > +{}; + +} // detail + +template +struct find_index; + +template class TT, class... Ts> +struct find_index> : detail::find_index_impl<0, T, Ts...> {}; + +template +inline constexpr std::size_t find_index_v = find_index::value; + + +template +struct is_in : std::disjunction...> {}; + +template +inline constexpr bool is_in_v = is_in::value; + +// ---------------------------------------------------------- + +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 +{ + static_assert(sizeof...(Ts) > 0); +}; + +template +inline constexpr bool exactly_once_v = exactly_once::value; + +} // iris + +#endif diff --git a/include/iris/type_traits.hpp b/include/iris/type_traits.hpp index 058d0dc..05098f5 100644 --- a/include/iris/type_traits.hpp +++ b/include/iris/type_traits.hpp @@ -146,158 +146,6 @@ struct symmetric_common_type : dominant_type // ----------------------------------------------------------- -template -struct type_list -{ - static constexpr std::size_t size = sizeof...(Ts); -}; - -template -struct constant_list -{ - static constexpr std::size_t size = sizeof...(Vals); -}; - -namespace detail { - -template -struct do_pack_indexing; - -template -struct do_pack_indexing> -{ - template - static std::type_identity select( - // ReSharper disable once CppCStyleCast - decltype((void*)Voids)..., - std::type_identity*, - ... - ); -}; - -template -struct do_cpack_indexing; - -template -struct do_cpack_indexing> -{ - template - static std::integral_constant select( - // ReSharper disable once CppCStyleCast - decltype((void*)Voids)..., - std::integral_constant*, - ... - ); -}; - -} // detail - - -template -struct at_c; - -template -using at_c_t = at_c::type; - -// Has native pack indexing? -// Note: GCC 15 emits "sorry, unimplemented: mangling type pack index" -#if __cpp_pack_indexing >= 202311L && \ - !(defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 15) && \ - !defined(__clang__) - -# define IRIS_PACK_INDEXING(I, Ts_ellipsis) Ts_ellipsis[I] - -template struct pack_indexing { using type = Ts...[I]; }; -template using pack_indexing_t = Ts...[I]; -template struct cpack_indexing { static constexpr auto value = Ns...[I]; }; -template constexpr auto cpack_indexing_v = Ns...[I]; - -template class TT, class... Ts> -struct at_c> -{ - using type = Ts...[I]; -}; - -// ---------------------------------------------------------- -#else // no native pack indexing -template -struct pack_indexing -{ - static_assert(I < sizeof...(Ts)); - using type = decltype(detail::do_pack_indexing>::select( - static_cast*>(nullptr)... - ))::type; -}; - -template -using pack_indexing_t = pack_indexing::type; - -# define IRIS_PACK_INDEXING(I, Ts_ellipsis) ::iris::pack_indexing_t - - -template -struct cpack_indexing -{ - static_assert(I < sizeof...(Ns)); - static constexpr auto value = decltype(detail::do_cpack_indexing>::select( - static_cast*>(nullptr)... - ))::value; -}; - -template -constexpr auto cpack_indexing_v = cpack_indexing::value; - - -template class TT, class... Ts> -struct at_c> -{ - static_assert(I < sizeof...(Ts)); - using type = decltype(detail::do_pack_indexing>::select( - static_cast*>(nullptr)... - ))::type; -}; -#endif - -// ---------------------------------------------------------- - - -inline constexpr std::size_t find_npos = static_cast(-1); - -namespace detail { - -template -struct find_index_impl - : std::integral_constant -{}; - -template -struct find_index_impl - : std::conditional_t< - std::is_same_v, - std::integral_constant, - find_index_impl - > -{}; - -} // detail - -template -struct find_index; - -template class TT, class... Ts> -struct find_index> : detail::find_index_impl<0, T, Ts...> {}; - -template -inline constexpr std::size_t find_index_v = find_index::value; - - -template -struct is_in : std::disjunction...> {}; - -template -inline constexpr bool is_in_v = is_in::value; - - template class F, class U, class... Ts> struct disjunction_for : std::disjunction...> {}; @@ -310,34 +158,7 @@ struct conjunction_for : std::conjunction...> {}; template class F, class U, class... Ts> inline constexpr bool conjunction_for_v = conjunction_for::value; - -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 -{ - static_assert(sizeof...(Ts) > 0); -}; - -template -inline constexpr bool exactly_once_v = exactly_once::value; - +// ----------------------------------------------------------- // Provides definition equivalent to MSVC's STL for semantic compatibility namespace detail::has_ADL_swap_detail { @@ -380,7 +201,7 @@ struct is_convertible_without_narrowing_array_check template requires requires (From&& x) { - { std::type_identity_t{std::forward(x)} } -> std::same_as; + { std::type_identity_t{static_cast(x)} } -> std::same_as; } struct is_convertible_without_narrowing_array_check : std::true_type diff --git a/include/iris/units/traits.hpp b/include/iris/units/traits.hpp index 79645a0..2193de1 100644 --- a/include/iris/units/traits.hpp +++ b/include/iris/units/traits.hpp @@ -8,6 +8,7 @@ // Don't include ; dependency ordering is important #include +#include #include #include diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 403b218..a03ca6b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -181,6 +181,7 @@ if(PROJECT_IS_TOP_LEVEL) IRIS_TEST_IRIS_TESTS library_config core + type_list type_traits ranges container_traits diff --git a/test/core.cpp b/test/core.cpp index c785453..c0476af 100644 --- a/test/core.cpp +++ b/test/core.cpp @@ -63,48 +63,6 @@ TEST_CASE("EBO") STATIC_CHECK(sizeof(Derived5_fixed) == 4); } -TEST_CASE("pack_indexing") -{ - STATIC_REQUIRE(std::is_same_v, int>); - STATIC_REQUIRE(std::is_same_v, int>); - STATIC_REQUIRE(std::is_same_v, float>); - - // make sure non-object and non-referenceable type is working - STATIC_REQUIRE(std::is_same_v, void>); - STATIC_REQUIRE(std::is_same_v, void>); - STATIC_REQUIRE(std::is_same_v, int>); - STATIC_REQUIRE(std::is_same_v, int>); - STATIC_REQUIRE(std::is_same_v, void>); - STATIC_REQUIRE(std::is_same_v, void>); - STATIC_REQUIRE(std::is_same_v, void>); - - STATIC_REQUIRE(std::is_same_v>, int>); - STATIC_REQUIRE(std::is_same_v>, int>); - STATIC_REQUIRE(std::is_same_v>, float>); -} - -TEST_CASE("exactly_once") -{ - STATIC_REQUIRE(iris::exactly_once_v>); - STATIC_REQUIRE_FALSE(iris::exactly_once_v>); -} - -TEST_CASE("is_in") -{ - STATIC_REQUIRE(iris::is_in_v); - STATIC_REQUIRE_FALSE(iris::is_in_v); -} - -TEST_CASE("find_index") -{ - STATIC_REQUIRE(iris::find_index_v> == 0); - STATIC_REQUIRE(iris::find_index_v> == 1); - STATIC_REQUIRE(iris::find_index_v> == 2); - STATIC_REQUIRE(iris::find_index_v> == iris::find_npos); - - STATIC_REQUIRE(iris::find_index_v> == 0); -} - TEST_CASE("Cpp17EqualityComparable") { STATIC_REQUIRE(iris::req::Cpp17EqualityComparable); diff --git a/test/rvariant/get_visit.cpp b/test/rvariant/get_visit.cpp index 08871e5..6bf130d 100644 --- a/test/rvariant/get_visit.cpp +++ b/test/rvariant/get_visit.cpp @@ -3,7 +3,7 @@ #include "iris_rvariant_test.hpp" #include -#include +#include #include #include diff --git a/test/type_list.cpp b/test/type_list.cpp new file mode 100644 index 0000000..ac5de05 --- /dev/null +++ b/test/type_list.cpp @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: MIT + +#include "iris_test.hpp" + +#include + +#include + +using iris::type_list; +using iris::concat_type_list; + +TEST_CASE("type_list") +{ + STATIC_CHECK(std::same_as::type, type_list<>>); + STATIC_CHECK(std::same_as>::type, type_list<>>); + STATIC_CHECK(std::same_as, type_list<>>::type, type_list<>>); + STATIC_CHECK(std::same_as, type_list<>, type_list<>>::type, type_list<>>); + + STATIC_CHECK(std::same_as, type_list<>>::type, type_list>); + STATIC_CHECK(std::same_as, type_list>::type, type_list>); + STATIC_CHECK(std::same_as, type_list>::type, type_list>); + + STATIC_CHECK(std::same_as, type_list<>, type_list<>>::type, type_list>); + STATIC_CHECK(std::same_as, type_list, type_list<>>::type, type_list>); + STATIC_CHECK(std::same_as, type_list<>, type_list>::type, type_list>); +} + +TEST_CASE("pack_indexing") +{ + STATIC_CHECK(std::same_as, int>); + STATIC_CHECK(std::same_as, int>); + STATIC_CHECK(std::same_as, float>); + + // make sure non-object and non-referenceable type is working + STATIC_CHECK(std::same_as, void>); + STATIC_CHECK(std::same_as, void>); + STATIC_CHECK(std::same_as, int>); + STATIC_CHECK(std::same_as, int>); + STATIC_CHECK(std::same_as, void>); + STATIC_CHECK(std::same_as, void>); + STATIC_CHECK(std::same_as, void>); + + STATIC_CHECK(std::same_as>, int>); + STATIC_CHECK(std::same_as>, int>); + STATIC_CHECK(std::same_as>, float>); +} + +TEST_CASE("exactly_once") +{ + STATIC_CHECK(iris::exactly_once_v>); + STATIC_CHECK_FALSE(iris::exactly_once_v>); +} + +TEST_CASE("is_in") +{ + STATIC_CHECK(iris::is_in_v); + STATIC_CHECK(!iris::is_in_v); +} + +TEST_CASE("find_index") +{ + STATIC_CHECK(iris::find_index_v> == 0); + STATIC_CHECK(iris::find_index_v> == 1); + STATIC_CHECK(iris::find_index_v> == 2); + STATIC_CHECK(iris::find_index_v> == iris::find_npos); + + STATIC_CHECK(iris::find_index_v> == 0); +} diff --git a/test/type_traits.cpp b/test/type_traits.cpp index 53c52c1..9f7fbc8 100644 --- a/test/type_traits.cpp +++ b/test/type_traits.cpp @@ -20,7 +20,7 @@ template struct tuple; template -struct type_list; +struct not_tuple; template struct n_tuple; @@ -618,9 +618,9 @@ TEST_CASE("specialization_of") STATIC_CHECK(iris::is_ttp_specialization_of_v, tuple>); STATIC_CHECK(iris::is_ttp_specialization_of_v, tuple>); - STATIC_CHECK(!iris::is_ttp_specialization_of_v, type_list>); - STATIC_CHECK(!iris::is_ttp_specialization_of_v, type_list>); - STATIC_CHECK(!iris::is_ttp_specialization_of_v, type_list>); + STATIC_CHECK(!iris::is_ttp_specialization_of_v, not_tuple>); + STATIC_CHECK(!iris::is_ttp_specialization_of_v, not_tuple>); + STATIC_CHECK(!iris::is_ttp_specialization_of_v, not_tuple>); STATIC_CHECK(iris::is_ctp_specialization_of_v, n_tuple>); STATIC_CHECK(iris::is_ctp_specialization_of_v, n_tuple>);