mirror of
				https://github.com/pocketpy/pocketpy
				synced 2025-10-30 16:30:16 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			641 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			641 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /***************************************************************************
 | |
| * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht          *
 | |
| * Copyright (c) QuantStack                                                 *
 | |
| *                                                                          *
 | |
| * Distributed under the terms of the BSD 3-Clause License.                 *
 | |
| *                                                                          *
 | |
| * The full license is in the file LICENSE, distributed with this software. *
 | |
| ****************************************************************************/
 | |
| 
 | |
| #ifndef XTL_XMETA_UTILS_HPP
 | |
| #define XTL_XMETA_UTILS_HPP
 | |
| 
 | |
| #include <cstddef>
 | |
| #include <cstdint>
 | |
| #include <type_traits>
 | |
| 
 | |
| #include "xfunctional.hpp"
 | |
| #include "xtl_config.hpp"
 | |
| 
 | |
| namespace xtl
 | |
| {
 | |
|     // TODO move to a xutils if we have one
 | |
| 
 | |
|     // gcc 4.9 is affected by C++14 defect CGW 1558
 | |
|     // see http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1558
 | |
|     template <class... T>
 | |
|     struct make_void
 | |
|     {
 | |
|         using type = void;
 | |
|     };
 | |
| 
 | |
|     template <class... T>
 | |
|     using void_t = typename make_void<T...>::type;
 | |
| 
 | |
|     namespace mpl
 | |
|     {
 | |
|         /*************
 | |
|          * mpl types *
 | |
|          *************/
 | |
| 
 | |
|         template <class... T>
 | |
|         struct vector
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         template <bool B>
 | |
|         using bool_ = std::integral_constant<bool, B>;
 | |
| 
 | |
|         template <std::size_t S>
 | |
|         using size_t_ = std::integral_constant<std::size_t, S>;
 | |
| 
 | |
|         /*******
 | |
|          * if_ *
 | |
|          *******/
 | |
| 
 | |
|         template <bool B, class T, class F>
 | |
|         struct if_c : std::conditional<B, T, F>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         template <bool B, class T, class F>
 | |
|         using if_c_t = typename if_c<B, T, F>::type;
 | |
| 
 | |
|         template <class B, class T, class F>
 | |
|         struct if_ : if_c<B::value, T, F>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         template <class B, class T, class F>
 | |
|         using if_t = typename if_<B, T, F>::type;
 | |
| 
 | |
|         /***********
 | |
|          * eval_if *
 | |
|          ***********/
 | |
| 
 | |
|         template <bool B, class T, class F>
 | |
|         struct eval_if_c
 | |
|         {
 | |
|             using type = typename T::type;
 | |
|         };
 | |
| 
 | |
|         template <class T, class F>
 | |
|         struct eval_if_c<false, T, F>
 | |
|         {
 | |
|             using type = typename F::type;
 | |
|         };
 | |
| 
 | |
|         template <class B, class T, class F>
 | |
|         struct eval_if : eval_if_c<B::value, T, F>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         template <class B, class T, class F>
 | |
|         using eval_if_t = typename eval_if<B, T, F>::type;
 | |
| 
 | |
|         /********
 | |
|          * cast *
 | |
|          ********/
 | |
| 
 | |
|         namespace detail
 | |
|         {
 | |
|             template <class A, template <class...> class B>
 | |
|             struct cast_impl;
 | |
| 
 | |
|             template <template <class...> class A, class... T, template <class...> class B>
 | |
|             struct cast_impl<A<T...>, B>
 | |
|             {
 | |
|                 using type = B<T...>;
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         template <class A, template <class...> class B>
 | |
|         struct cast : detail::cast_impl<A, B>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         template <class A, template <class...> class B>
 | |
|         using cast_t = typename cast<A, B>::type;
 | |
| 
 | |
|         /********
 | |
|          * size *
 | |
|          ********/
 | |
| 
 | |
|         namespace detail
 | |
|         {
 | |
|             template <class L>
 | |
|             struct size_impl;
 | |
| 
 | |
|             template <template <class...> class F, class... T>
 | |
|             struct size_impl<F<T...>> : size_t_<sizeof...(T)>
 | |
|             {
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         template <class L>
 | |
|         struct size : detail::size_impl<L>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         /*********
 | |
|          * empty *
 | |
|          *********/
 | |
| 
 | |
|         namespace detail
 | |
|         {
 | |
|             template <class L>
 | |
|             struct empty_impl;
 | |
| 
 | |
|             template <template <class...> class F, class... T>
 | |
|             struct empty_impl<F<T...>> : bool_<sizeof...(T) == std::size_t(0)>
 | |
|             {
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         template <class L>
 | |
|         struct empty : detail::empty_impl<L>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         template <class L>
 | |
|         using empty_t = typename empty<L>::type;
 | |
| 
 | |
|         /********
 | |
|          * plus *
 | |
|          ********/
 | |
| 
 | |
|         namespace detail
 | |
|         {
 | |
|             template <class... T>
 | |
|             struct plus_impl;
 | |
| 
 | |
|             template <>
 | |
|             struct plus_impl<> : size_t_<0>
 | |
|             {
 | |
|             };
 | |
| 
 | |
|             template <class T1, class... T>
 | |
|             struct plus_impl<T1, T...> : size_t_<T1::value + plus_impl<T...>::value>
 | |
|             {
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         template <class... T>
 | |
|         struct plus : detail::plus_impl<T...>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         /*********
 | |
|          * count *
 | |
|          *********/
 | |
| 
 | |
|         namespace detail
 | |
|         {
 | |
|             template <class L, class V>
 | |
|             struct count_impl;
 | |
| 
 | |
|             template <template <class...> class L, class... T, class V>
 | |
|             struct count_impl<L<T...>, V> : plus<std::is_same<T, V>...>
 | |
|             {
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         template <class L, class V>
 | |
|         struct count : detail::count_impl<L, V>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         /************
 | |
|          * count_if *
 | |
|          ************/
 | |
| 
 | |
|         namespace detail
 | |
|         {
 | |
|             template <class L, template <class> class P>
 | |
|             struct count_if_impl;
 | |
| 
 | |
|             template <template <class...> class L, class... T, template <class> class P>
 | |
|             struct count_if_impl<L<T...>, P> : plus<P<T>...>
 | |
|             {
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         template <class L, template <class> class P>
 | |
|         struct count_if : detail::count_if_impl<L, P>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         /************
 | |
|          * index_of *
 | |
|          ************/
 | |
| 
 | |
|         namespace detail
 | |
|         {
 | |
|             template <class L, class V>
 | |
|             struct index_of_impl;
 | |
| 
 | |
|             template <template <class...> class L, class V>
 | |
|             struct index_of_impl<L<>, V>
 | |
|             {
 | |
|                 static constexpr size_t value = SIZE_MAX;
 | |
|             };
 | |
| 
 | |
|             template <template <class...> class L, class... T, class V>
 | |
|             struct index_of_impl<L<V, T...>, V>
 | |
|             {
 | |
|                 static constexpr size_t value = 0u;
 | |
|             };
 | |
| 
 | |
|             template <template <class...> class L, class U, class... T, class V>
 | |
|             struct index_of_impl<L<U, T...>, V>
 | |
|             {
 | |
|                 static constexpr size_t tmp = index_of_impl<L<T...>, V>::value;
 | |
|                 static constexpr size_t value = tmp == SIZE_MAX ? SIZE_MAX : 1u + tmp;
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         template <class L, class T>
 | |
|         struct index_of : detail::index_of_impl<L, T>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         /************
 | |
|          * contains *
 | |
|          ************/
 | |
| 
 | |
|         namespace detail
 | |
|         {
 | |
|             template <class L, class V>
 | |
|             struct contains_impl;
 | |
| 
 | |
|             template <template <class...> class L, class V>
 | |
|             struct contains_impl<L<>, V> : std::false_type
 | |
|             {
 | |
|             };
 | |
| 
 | |
|             template <template <class...> class L, class... T, class V>
 | |
|             struct contains_impl<L<V, T...>, V> : std::true_type
 | |
|             {
 | |
|             };
 | |
| 
 | |
|             template <template <class...> class L, class U, class... T, class V>
 | |
|             struct contains_impl<L<U, T...>, V> : contains_impl<L<T...>, V>
 | |
|             {
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         template <class L, class V>
 | |
|         struct contains : detail::contains_impl<L, V>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         /*********
 | |
|          * front *
 | |
|          *********/
 | |
| 
 | |
|         namespace detail
 | |
|         {
 | |
|             template <class L>
 | |
|             struct front_impl;
 | |
| 
 | |
|             template <template <class...> class L, class T, class... U>
 | |
|             struct front_impl<L<T, U...>>
 | |
|             {
 | |
|                 using type = T;
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         template <class L>
 | |
|         struct front : detail::front_impl<L>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         template <class L>
 | |
|         using front_t = typename front<L>::type;
 | |
| 
 | |
|         /********
 | |
|          * back *
 | |
|          ********/
 | |
| 
 | |
|         namespace detail
 | |
|         {
 | |
|             template <class L>
 | |
|             struct back_impl;
 | |
| 
 | |
|             template <template <class...> class L, class T>
 | |
|             struct back_impl<L<T>>
 | |
|             {
 | |
|                 using type = T;
 | |
|             };
 | |
| 
 | |
|             // Compilation time improvement
 | |
|             template <template <class...> class L, class T1, class T2>
 | |
|             struct back_impl<L<T1, T2>>
 | |
|             {
 | |
|                 using type = T2;
 | |
|             };
 | |
| 
 | |
|             template <template <class...> class L, class T1, class T2, class T3>
 | |
|             struct back_impl<L<T1, T2, T3>>
 | |
|             {
 | |
|                 using type = T3;
 | |
|             };
 | |
| 
 | |
|             template <template <class...> class L, class T1, class T2, class T3, class T4>
 | |
|             struct back_impl<L<T1, T2, T3, T4>>
 | |
|             {
 | |
|                 using type = T4;
 | |
|             };
 | |
| 
 | |
|             template <template <class...> class L, class T, class... U>
 | |
|             struct back_impl<L<T, U...>> : back_impl<L<U...>>
 | |
|             {
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         template <class L>
 | |
|         struct back : detail::back_impl<L>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         template <class L>
 | |
|         using back_t = typename back<L>::type;
 | |
| 
 | |
|         /**************
 | |
|          * push_front *
 | |
|          **************/
 | |
| 
 | |
|         namespace detail
 | |
|         {
 | |
|             template <class L, class... T>
 | |
|             struct push_front_impl;
 | |
| 
 | |
|             template <template <class...> class L, class... U, class... T>
 | |
|             struct push_front_impl<L<U...>, T...>
 | |
|             {
 | |
|                 using type = L<T..., U...>;
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         template <class L, class... T>
 | |
|         struct push_front : detail::push_front_impl<L, T...>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         template <class L, class... T>
 | |
|         using push_front_t = typename push_front<L, T...>::type;
 | |
| 
 | |
|         /*************
 | |
|          * push_back *
 | |
|          *************/
 | |
| 
 | |
|         namespace detail
 | |
|         {
 | |
|             template <class L, class... T>
 | |
|             struct push_back_impl;
 | |
| 
 | |
|             template <template <class...> class L, class... U, class... T>
 | |
|             struct push_back_impl<L<U...>, T...>
 | |
|             {
 | |
|                 using type = L<U..., T...>;
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         template <class L, class... T>
 | |
|         struct push_back : detail::push_back_impl<L, T...>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         template <class L, class... T>
 | |
|         using push_back_t = typename push_back<L, T...>::type;
 | |
| 
 | |
|         /*************
 | |
|          * pop_front *
 | |
|          *************/
 | |
| 
 | |
|         namespace detail
 | |
|         {
 | |
|             template <class L>
 | |
|             struct pop_front_impl;
 | |
| 
 | |
|             template <template <class...> class L, class T, class... U>
 | |
|             struct pop_front_impl<L<T, U...>>
 | |
|             {
 | |
|                 using type = L<U...>;
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         template <class L>
 | |
|         struct pop_front : detail::pop_front_impl<L>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         template <class L>
 | |
|         using pop_front_t = typename pop_front<L>::type;
 | |
| 
 | |
|         /*************
 | |
|          * transform *
 | |
|          *************/
 | |
| 
 | |
|         namespace detail
 | |
|         {
 | |
|             template <template <class...> class F, class L>
 | |
|             struct transform_impl;
 | |
| 
 | |
|             template <template <class...> class F, template <class...> class L, class... T>
 | |
|             struct transform_impl<F, L<T...>>
 | |
|             {
 | |
|                 using type = L<F<T>...>;
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         template <template <class...> class F, class L>
 | |
|         struct transform : detail::transform_impl<F, L>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         template <template <class...> class F, class L>
 | |
|         using transform_t = typename transform<F, L>::type;
 | |
| 
 | |
|         /*************
 | |
|          * merge_set *
 | |
|          *************/
 | |
| 
 | |
|         namespace detail
 | |
|         {
 | |
|             template <class S1, class S2>
 | |
|             struct merge_set_impl;
 | |
| 
 | |
|             template <template <class...> class L, class... T>
 | |
|             struct merge_set_impl<L<T...>, L<>>
 | |
|             {
 | |
|                 using type = L<T...>;
 | |
|             };
 | |
| 
 | |
|             template <template <class...> class L, class... T, class U1, class... U>
 | |
|             struct merge_set_impl<L<T...>, L<U1, U...>>
 | |
|             {
 | |
|                 using type = typename merge_set_impl<if_t<contains<L<T...>, U1>,
 | |
|                                                           L<T...>,
 | |
|                                                           L<T..., U1>>,
 | |
|                                                      L<U...>>::type;
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         template <class S1, class S2>
 | |
|         struct merge_set : detail::merge_set_impl<S1, S2>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         template <class S1, class S2>
 | |
|         using merge_set_t = typename merge_set<S1, S2>::type;
 | |
| 
 | |
|         /***********
 | |
|          * find_if *
 | |
|          ***********/
 | |
| 
 | |
|         template <template <class> class Test, class L>
 | |
|         struct find_if;
 | |
| 
 | |
|         namespace detail
 | |
|         {
 | |
|             template <template <class> class Test, std::size_t I, class... T>
 | |
|             struct find_if_impl;
 | |
| 
 | |
|             template <template <class> class Test, std::size_t I>
 | |
|             struct find_if_impl<Test, I> : size_t_<I>
 | |
|             {
 | |
|             };
 | |
| 
 | |
|             template <template <class> class Test, std::size_t I, class T0, class... T>
 | |
|             struct find_if_impl<Test, I, T0, T...> : std::conditional_t<Test<T0>::value,
 | |
|                                                                         size_t_<I>,
 | |
|                                                                         find_if_impl<Test, I + 1, T...>>
 | |
|             {
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         template <template <class> class Test, template <class...> class L, class... T>
 | |
|         struct find_if<Test, L<T...>> : detail::find_if_impl<Test, 0, T...>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         /*********
 | |
|          * split *
 | |
|          *********/
 | |
| 
 | |
|         namespace detail
 | |
|         {
 | |
|             template <std::size_t N, class L1, class L2>
 | |
|             struct transfer
 | |
|             {
 | |
|                 using new_l1 = push_back_t<L1, front_t<L2>>;
 | |
|                 using new_l2 = pop_front_t<L2>;
 | |
|                 using new_transfer = transfer<N - 1, new_l1, new_l2>;
 | |
|                 using first_type = typename new_transfer::first_type;
 | |
|                 using second_type = typename new_transfer::second_type;
 | |
|             };
 | |
| 
 | |
|             template <class L1, class L2>
 | |
|             struct transfer<0, L1, L2>
 | |
|             {
 | |
|                 using first_type = L1;
 | |
|                 using second_type = L2;
 | |
|             };
 | |
| 
 | |
|             template <std::size_t N, class L>
 | |
|             struct split_impl
 | |
|             {
 | |
|                 using tr_type = transfer<N, vector<>, L>;
 | |
|                 using first_type = typename tr_type::first_type;
 | |
|                 using second_type = typename tr_type::second_type;
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         template <std::size_t N, class L>
 | |
|         struct split : detail::split_impl<N, L>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         /**********
 | |
|          * unique *
 | |
|          **********/
 | |
| 
 | |
|         namespace detail
 | |
|         {
 | |
|             template <class L>
 | |
|             struct unique_impl;
 | |
| 
 | |
|             template <template <class...> class L, class... T>
 | |
|             struct unique_impl<L<T...>>
 | |
|             {
 | |
|                 using type = merge_set_t<L<>, L<T...>>;
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         template <class L>
 | |
|         struct unique : detail::unique_impl<L>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         template <class L>
 | |
|         using unique_t = typename unique<L>::type;
 | |
| 
 | |
|         /*************
 | |
|          * static_if *
 | |
|          *************/
 | |
| 
 | |
|         template <class TF, class FF>
 | |
|         decltype(auto) static_if(std::true_type, const TF& tf, const FF&)
 | |
|         {
 | |
|             return tf(identity());
 | |
|         }
 | |
| 
 | |
|         template <class TF, class FF>
 | |
|         decltype(auto) static_if(std::false_type, const TF&, const FF& ff)
 | |
|         {
 | |
|             return ff(identity());
 | |
|         }
 | |
| 
 | |
|         template <bool cond, class TF, class FF>
 | |
|         decltype(auto) static_if(const TF& tf, const FF& ff)
 | |
|         {
 | |
|             return static_if(std::integral_constant<bool, cond>(), tf, ff);
 | |
|         }
 | |
| 
 | |
|         /***********
 | |
|          * switch_ *
 | |
|          ***********/
 | |
| 
 | |
|         using default_t = std::true_type;
 | |
| 
 | |
|         namespace detail
 | |
|         {
 | |
|             template <class... T>
 | |
|             struct switch_impl;
 | |
| 
 | |
|             template <class C, class T, class... U>
 | |
|             struct switch_impl<C, T, U...>
 | |
|                 : std::conditional<C::value, T, typename switch_impl<U...>::type>
 | |
|             {
 | |
|             };
 | |
| 
 | |
|             template <class C, class T, class U>
 | |
|             struct switch_impl<C, T, default_t, U>
 | |
|                 : std::conditional<C::value, T, U>
 | |
|             {
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         template <class... T>
 | |
|         struct switch_ : detail::switch_impl<T...>
 | |
|         {
 | |
|         };
 | |
| 
 | |
|         template <class... T>
 | |
|         using switch_t = typename switch_<T...>::type;
 | |
|     }
 | |
| }
 | |
| 
 | |
| #endif
 |