| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640 |
- /***************************************************************************
- * 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
|