From 1bb64f04739725cc1e36f137df4a2ea6358ee358 Mon Sep 17 00:00:00 2001 From: Patrick Wuttke Date: Tue, 17 Feb 2026 10:24:34 +0100 Subject: [PATCH] Added utility functions for modifying type argument lists. --- source/mijin/util/traits.hpp | 320 ++++++++++++++++++++++++++++++----- 1 file changed, 273 insertions(+), 47 deletions(-) diff --git a/source/mijin/util/traits.hpp b/source/mijin/util/traits.hpp index 5a8ce3d..0a57fe7 100644 --- a/source/mijin/util/traits.hpp +++ b/source/mijin/util/traits.hpp @@ -4,7 +4,9 @@ #if !defined(MIJIN_UTIL_TRAITS_HPP_INCLUDED) #define MIJIN_UTIL_TRAITS_HPP_INCLUDED 1 +#include #include +#include namespace mijin { @@ -24,6 +26,61 @@ namespace mijin struct Type_; // use as typevar struct Any_; // use as placeholder in templates +template +struct TypeVar {}; + +template +struct Type +{ + using type_t = T; + + template + constexpr bool operator==(Type) const noexcept + { + return std::is_same_v; + } + + template + constexpr bool operator!=(Type) const noexcept + { + return !std::is_same_v; + } +}; + +template +struct type_func +{ + template + static constexpr auto value = func(Type()...); + + template + struct type { + static constexpr auto value = func(Type()...); + }; +}; + +template +struct value_list +{ + template + static constexpr auto apply(TFunc&& func) + { + return std::invoke(std::forward(func), Values...); + } + + template + static constexpr void forEach(TFunc func) + { + (std::invoke(func, Values), ...); + } + + template + static constexpr void forEachStatic(TFunc func) + { + (std::invoke(func, std::integral_constant, Values>()), ...); + } +}; + template struct always_false { @@ -42,46 +99,207 @@ struct always_false_val template inline constexpr bool always_false_val_v = always_false_val::value; -template typename TFilter, typename... TArgs> -struct TypeFilter; - -template typename TFilter> -struct TypeFilter +template +struct TypeAtHelper { - using type_t = std::tuple<>; + using type_t = typename TypeAtHelper::type_t; }; -template typename TFilter, typename TFirst, typename... TArgs> -struct TypeFilter +template +struct TypeAtHelper<0, TArg, TArgs...> { - static consteval auto makeTypeHelper() - { - using base_t = typename TypeFilter::type_t; + using type_t = TArg; +}; +template +using type_at_t = typename TypeAtHelper::type_t; - // note: not using decltype, as the compiler might think it is being evaluated - if constexpr (!TFilter::value) { - return static_cast(nullptr); +template typename TTo> +struct copy_args; + +template typename TFrom, template typename TTo, typename... TArgs> +struct copy_args, TTo> { + using type = TTo; +}; + +template typename TTo> +using copy_args_t = typename copy_args::type; + +template +struct replace_type; + +template typename TTmpl, typename TFrom, typename TTo, typename... TArgs> +struct replace_type, TFrom, TTo> +{ + using type = TTmpl, TTo, TArgs>...>; +}; + +template +using replace_type_t = typename replace_type::type; + +template +struct ReplaceTypevarsHelper; + +template +struct ReplaceTypevarsHelper +{ + using type = replace_type_t::type, TypeVar, TFirst>; +}; + +template +struct ReplaceTypevarsHelper +{ + using type = TTmpl; +}; + +template +using replace_typevars_t = typename ReplaceTypevarsHelper::type; + +template +struct prepend_type; + +template typename TTmpl, typename TType, typename... TArgs> +struct prepend_type, TType> +{ + using type = TTmpl; +}; + +template +using prepend_type_t = typename prepend_type::type; + +template +struct concat_types; + +template typename TTmplA, template typename TTmplB, typename... TArgsA, typename... TArgsB> +struct concat_types, TTmplB> +{ + using type = TTmplA; +}; + +template +struct concat_types +{ + using type = typename concat_types::type, TMore...>::type; +}; + +template +struct concat_types +{ + using type = TTmpl; +}; + +template +using concat_types_t = typename concat_types::type; + +template +struct drop_types; + +template typename TTmpl, std::size_t count, typename TFirst, typename... TArgs> +struct drop_types, count> +{ + using type = std::remove_pointer_t>(nullptr); } else { - auto wrapper = [](std::tuple*) - { - return static_cast*>(nullptr); - }; - return wrapper(static_cast(nullptr)); + return std::add_pointer_t, count-1>::type>(nullptr); } - } - - using type_t = std::remove_pointer_t; + }())>; }; -template typename TFilter, typename... TArgs> -auto typeFilterHelper(std::tuple*) +template typename TTmpl> +struct drop_types, 0> { - return static_cast::type_t*>(nullptr); -} + using type = TTmpl<>; +}; -template typename TFilter, typename TTuple> -using filter_types_t = std::remove_pointer_t(static_cast(nullptr)))>; +template +using drop_types_t = typename drop_types::type; + +template +struct crop_types; + +template typename TTmpl, std::size_t count, typename TFirst, typename... TArgs> +struct crop_types, count> +{ + using type = std::remove_pointer_t>(nullptr); + } + else { + return std::add_pointer_t, count-1>::type, TFirst>>(nullptr); + } + }())>; +}; + +template typename TTmpl> +struct crop_types, 0> +{ + using type = TTmpl<>; +}; + +template +using crop_types_t = typename crop_types::type; + +template +struct insert_type; + +template typename TTmpl, std::size_t idx, typename... TTypes, typename... TArgs> +struct insert_type, idx, TTypes...> +{ + using type = concat_types_t, idx>, TTmpl, drop_types_t, idx>>; +}; + +template +using insert_type_t = typename insert_type::type; + +template typename TFilter, typename... TFilterArgs> +struct TypeFilter; + +template typename TFilter, typename TFirstFilterArg, typename... TFilterArgs> +struct TypeFilter +{ + using filter_t = TFilter; + template + struct Inner + { + using type_t = std::remove_pointer_t*)(nullptr); + } + else + { + using base_t = drop_types_t>; + using current_t = type_at_t<0, TTypes...>; + using inner_filter_t = replace_typevars_t; + if constexpr (inner_filter_t::value) { + return std::add_pointer_t(nullptr); + } + else { + return std::add_pointer_t>(nullptr); + } + } + }())>; + }; + + template + using type = typename copy_args_t::type_t; +}; + +template typename TFilter> +struct TypeFilter +{ + template + using type = typename TypeFilter>::template type; +}; + +template typename TFilter, typename TTuple, typename... TFilterArgs> +using remove_type_if_t = typename TypeFilter::template type; + +template +using remove_type_if_fn_t = remove_type_if_t::template type, TTuple, TFilterArgs...>; + +template +using remove_type_t = remove_type_if_t>;// remove_type_if_fn_t<[](auto type) { return type == Type(); }, std::tuple>; template typename TPredicate, typename... TArgs> auto mapTypesHelper(std::tuple) @@ -105,7 +323,7 @@ template typename TTemplate, typename... TArgs> struct is_template_instance> : std::true_type {}; template typename TTemplate, typename TType> -constexpr bool is_template_instance_v = is_template_instance::value; +inline constexpr bool is_template_instance_v = is_template_instance::value; namespace impl { @@ -137,7 +355,7 @@ template typename TTemplate, typename TType, typename... T struct match_template_type, TType> : impl::tmpl_param_comparator::template matches_t {}; template -constexpr bool match_template_type_v = match_template_type::value; +inline constexpr bool match_template_type_v = match_template_type::value; // similar to std::is_same, but allows placeholders // - is_type_or_impl, some_type> resolves to some_tmpl @@ -176,7 +394,7 @@ template struct match_any_type : std::disjunction...> {}; template -static constexpr bool match_any_type_v = match_any_type::value; +inline constexpr bool match_any_type_v = match_any_type::value; template concept union_type = match_any_type_v; @@ -190,7 +408,7 @@ struct is_type_member> {}; template -constexpr bool is_type_member_v = is_type_member::value; +inline constexpr bool is_type_member_v = is_type_member::value; template struct is_member_object_pointer_of : std::false_type {}; @@ -216,21 +434,6 @@ using copy_cv_t = copy_const_t>; template using delay_type_t = TActual; - -template -struct TypeAtHelper -{ - using type_t = typename TypeAtHelper::type_t; -}; - -template -struct TypeAtHelper<0, TArg, TArgs...> -{ - using type_t = TArg; -}; -template -using type_at_t = TypeAtHelper::type_t; - template typename TOper, typename... TArgs> struct detect_or { @@ -248,6 +451,10 @@ struct detect_or template typename TOper, typename... TArgs> using detect_or_t = detect_or::type; + +template typename TOper, typename... TArgs> +inline constexpr bool detected_v = detect_or::detected; + struct empty_type {}; template @@ -279,6 +486,25 @@ decltype(auto) delayEvaluation(TType&& value) #if MIJIN_STATIC_TESTS namespace test { +static_assert(std::is_same_v, std::tuple>, std::tuple>); +static_assert(std::is_same_v, std::tuple<>>, std::tuple>); +static_assert(std::is_same_v>, std::tuple>); + +static_assert(std::is_same_v, 0>, std::tuple>); +static_assert(std::is_same_v, 1>, std::tuple>); +static_assert(std::is_same_v, 2>, std::tuple>); +static_assert(std::is_same_v, 3>, std::tuple<>>); + +static_assert(std::is_same_v, 0>, std::tuple<>>); +static_assert(std::is_same_v, 1>, std::tuple>); +static_assert(std::is_same_v, 2>, std::tuple>); +static_assert(std::is_same_v, 3>, std::tuple>); + +static_assert(std::is_same_v, 1, double>, std::tuple>); +static_assert(std::is_same_v, 1, double, float>, std::tuple>); +static_assert(std::is_same_v, 0, double>, std::tuple>); +static_assert(std::is_same_v, 2, double>, std::tuple>); + template struct MyTemplate {};