|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866 |
- /*!
- * \file typelist.h
- * \brief A template parameter "container"
- *
- * Copyright (C) 2018-2019 Christos Choutouridis
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #ifndef __utl_meta_pack_h__
- #define __utl_meta_pack_h__
-
- #include <utl/core/impl.h>
- #include <utl/meta/integral.h>
- #include <utl/meta/idx_sequence.h>
- #include <utl/meta/detection.h>
- #include <utl/meta/invoke.h>
- #include <utl/meta/sfinae.h>
- /*!
- * \ingroup meta
- * \defgroup typelist
- */
- //! @{
-
- namespace utl {
- namespace meta {
-
- /*!
- * \brief
- * A class template that just holds a parameter pack.
- *
- * The idea came from MPL's sequence concept[1] and from N4115[2].
- * In addition to N4115's name "packer" we just prefer a name which is object, not a subject.
- * This way the name gives the feeling of a container and smells like Python.
- *
- * In addition to tuple we lack members, so typelist could serve as an empty base class,
- * and an object of the ultimate type could always be instantiated
- * (even if the parameter typelist contains void or some type that lacks
- * a default constructor).
- * \example
- * \code
- * using l1 = typelist<int, void*, double, void>;
- * l1 a {};
- * \endcode
- *
- * boost::hana[3] suggests a more powerful scheme were type invariant structures can be used
- * for metaprograming also. This lib does not need (yet) this kind of power (we afraid the
- * responsibility that comes along). So a simple python-like list with some extra vector-like
- * element access functionalities and no iterators is good enough(for now).
- *
- * [1]: https://www.boost.org/doc/
- * [2]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4115.html
- * [3]: https://github.com/boostorg/hana
- */
- template <typename... Ts>
- struct typelist {
- using type = typelist; //!< act as identity
-
- //! \return sizeof...(Ts)
- static constexpr size_t size() noexcept {
- return sizeof...(Ts);
- }
- //! \return true if empty
- static constexpr bool empty() noexcept {
- return (sizeof...(Ts) == 0);
- }
- // ======= times utility =======
- private:
- template<size_t N, typename L, typename ...T>
- struct times_ { };
-
- template<size_t N, typename ...L>
- struct times_<N, typelist<L...>, Ts...> {
- // append one and recurse
- using type = type_<
- if_c <N != 0,
- times_<N-1, typelist<L..., Ts...>, Ts...>,
- typelist<L...>
- >>;
- };
- public:
- /*!
- * Generate typelist<Ts..., Ts..., ...> of size \c N arguments.
- * \example
- * \code
- * static_assert (
- * std::is_same<typelist<int, char>::times<2>,
- * typelist<int, char, int, char>
- * >, "" );
- * \endcode
- * complexity \f$ O(N) \f$
- */
- template<size_t N>
- using times = type_<
- times_<N, typelist<>, Ts...>
- >;
- };
-
- /*!
- * An integral constant wrapper that is the size of the \c meta::typelist
- *
- * Complexity \f$ O(1) \f$.
- *
- * \param List A typelist
- * \return The size of the typelist
- */
- template <typename List>
- using size = size_<List::size()>;
-
- /*!
- * An Boolean constant wrapper that returns if the typelist is empty
- *
- * Complexity \f$ O(1) \f$.
- *
- * \param List A typelist
- * \return Empty or not
- */
- template <typename List>
- using empty = bool_<List::empty()>;
-
- //! pair
- //! A special typelist with only 2 Types
- template <typename T1, typename T2>
- using pair = typelist<T1, T2>;
-
-
- //! repeat
- //! @{
-
- /*!
- * A wrapper to typelist<>::times<> utility for integer argument \p N
- */
- template <size_t N, typename ...Ts>
- using repeat_c = typename typelist<Ts...>::template times<N>;
-
- /*!
- * A wrapper to typelist<>::times<> utility for integral_c argument \p N
- */
- template <typename N, typename ...Ts>
- using repeat = repeat_c<N::type::value, Ts...>;
- //! @}
-
- /*!
- * Apply
- * An analogous to apply() implementation for tuples. We just use
- * Our typelist<> and integer_sequence<> types.
- */
- //! @{
- namespace apply_impl {
- template <typename Fn, typename Seq>
- struct apply_ { };
-
- //! \p Sequence == typelist<>
- template<typename Fn, typename ...List>
- struct apply_<Fn, typelist<List...>> {
- using type = invoke<Fn, List...>;
- };
- //! Sequence == integer_sequence<>
- template <typename Fn, typename T, T... Is>
- struct apply_<Fn, integer_sequence<T, Is...>> {
- using type = invoke<Fn, integral_<T, Is>...>;
- };
- }
-
- /*!
- * Apply the Invocable \p Fn using the types in the type \p Seq as arguments.
- * \note
- * This is the opposed operation of typelist<Ts...>
- *
- * If \p Seq == typelist<> then
- * Unpack typelist and apply to \c Fn
- * It \p Seq == integer_sequence<> then
- * Unpack and use the integral_c<> of each integer
- */
- template <typename Fn, typename Seq>
- using apply = apply_impl::apply_<Fn, Seq>;
-
- //! @}
-
- /*
- * ========= element access ========
- */
- //! at: random element access
- //! @{
- namespace at_impl {
-
- template <typename T> struct _as_pointer__ { using type = T*; };
- template <typename T> struct _as_pointer__<T*> { using type = T*; };
- template <typename T> using as_pointer_ = eval<
- _as_pointer__<T>
- >;
-
- template <typename ...>
- struct at_head_ { };
-
- template <typename... voids>
- struct at_head_ <typelist<voids...>> {
- // successful selection N voids, one T* and the rest
- template <typename T> static constexpr T select(voids..., T*, ...);
- // selection on error
- static constexpr nil_ select (...);
- };
-
- template<typename List, index_t N>
- struct at_ { };
-
- template<typename... List, index_t N>
- struct at_<typelist<List...>, N> {
- using head_ = at_head_<typelist<void*>::times<N>>; //< make at_head_<> with N void*
- using type = decltype(
- head_::select(static_cast<as_pointer_<List>>(nullptr)...) //< pass all as List*...
- );
- };
- }
-
- /*!
- * Return the \p N th element in the \c meta::typelist \p List.
- *
- * Complexity \f$ O(N) \f$.
- */
- template <typename List, index_t N>
- using at_c = eval<
- at_impl::at_<List, N>
- >;
-
- /*!
- * Return the \p N th element in the \c meta::typelist \p List.
- *
- * Complexity \f$ O(N) \f$.
- */
- template <typename List, typename N>
- using at = at_c<List, N::type::value>;
- //!@}
-
-
- //! front
- //! @{
- namespace front_impl {
- template <typename L>
- struct front_ { };
-
- template <typename Head, typename... Tail>
- struct front_<typelist<Head, Tail...>> {
- using type = Head;
- };
- }
-
- //! Return the first element in \c meta::typelist \p List.
- //! Complexity \f$ O(1) \f$.
- template <typename List>
- using front = eval<
- front_impl::front_<List>
- >;
- //! @}
-
- //! back
- //! @{
- namespace back_impl {
- template <typename List>
- struct back_ { };
-
- template <typename Head, typename... Tail>
- struct back_<typelist<Head, Tail...>> {
- using type = at_c <
- typelist<Head, Tail...>, sizeof...(Tail)
- >;
- };
- }
-
- //! Return the last element in \c meta::typelist \p List.
- //! Complexity \f$ O(N) \f$.
- template <typename List>
- using back = eval<
- back_impl::back_<List>
- >;
- //! @}
- /*
- * ========= typelist operations =========
- */
-
- //! Concatenation
- //! @{
- namespace cat_impl {
- template <typename... Lists>
- struct cat_ { };
-
- template <>
- struct cat_<> {
- using type = typelist<>;
- };
-
- template <typename... L1>
- struct cat_<typelist<L1...>> {
- using type = typelist<L1...>;
- };
-
- template <typename... L1, typename... L2>
- struct cat_<typelist<L1...>, typelist<L2...>> {
- using type = typelist<L1..., L2...>;
- };
-
- template <typename... L1, typename... L2, typename... Ln>
- struct cat_<typelist<L1...>, typelist<L2...>, Ln...>
- : cat_ <typelist<L1..., L2...>, Ln...> { };
-
- }
-
- /*!
- * Transformation that concatenates several lists into a single typelist.
- * The parameters must all be instantiations of \c meta::typelist.
- * Complexity: \f$ O(N) \f$
- * where \f$ N \f$ is the number of lists passed to the algorithm.
- */
- template <typename... Lists>
- using cat = eval<
- cat_impl::cat_<Lists...>
- >;
- //! @}
-
-
- //! fold<List, V, Fn>, rev_fold<List, V, Fn>
- //! @{
- namespace fold_impl {
- // fold<<T1, T2, T3>, V, F> == F<F<F<V, T1>, T2>, T3>
- template<typename, typename, typename>
- struct fold_ { }; // ill formed
-
- // recursive call
- template<typename Head, typename... Tail,
- typename V,
- typename Fn>
- struct fold_<typelist<Head, Tail...>, V, Fn> {
- // recursive call of fold_ by consuming typelist and invoking Fn
- using type = eval<
- fold_<
- typelist<Tail...>,
- invoke<Fn, V, Head>,
- Fn
- >
- >;
- };
- // termination call
- template<typename V0, typename Fn>
- struct fold_<typelist<>, V0, Fn> {
- using type = V0;
- };
- }
-
- /*!
- * transform the \p List to a new one by doing a left fold using binary Invocable \p Fn
- * and initial value \p V
- * Complexity \f$ O(N) \f$
- * \example
- * fold<typelist<T1, T2, T3>, V, F> == F<F<F<V, T1>, T2>, T3>
- * \example
- * fold<typelist<>, V, F> == V
- * \param List The list to fold
- * \param V The initial item feeded to Fn
- * \param Fn The binary Invocable
- */
- template <typename List, typename V, typename Fn>
- using fold = eval<fold_impl::fold_<List, V, Fn>>;
-
- //! accumulate is an stl name for fold
- template <typename List, typename V, typename Fn>
- using accumulate = fold<List, V, Fn>;
-
- namespace rev_fold_impl {
-
- // rev_fold<<T1, T2, T3>, V, F> == F<T1, F<T2, F<T3, V>>>
- template<typename, typename, typename>
- struct rev_fold_ { }; // ill formed
-
- // recursive call
- template<typename Head, typename... Tail,
- typename V,
- typename Fn>
- struct rev_fold_<typelist<Head, Tail...>, V, Fn> {
- // recursive call inside invoke. This way the 2nd argument of Fn
- // becoming the recursive "thing", inside Fn<>
- using type = invoke <
- Fn, Head, eval<
- rev_fold_ <
- typelist<Tail...>,
- V,
- Fn
- >>
- >;
- };
- // pre-termination call
- template<typename Tail, typename V, typename Fn>
- struct rev_fold_ <typelist<Tail>, V, Fn> {
- using type = invoke<Fn, Tail, V>;
- };
- // termination call
- template<typename V, typename Fn>
- struct rev_fold_ <typelist<>, V, Fn> {
- using type = V;
- };
- }
-
- /*!
- * transform the \p List to a new one by doing a right fold using binary Invocable \p Fn
- * and initial value \p V
- * Complexity \f$ O(N) \f$
- * \example
- * rev_fold<typelist<T1, T2, T3>, V, F> == F<T1, F<T2, F<T3, V>>>
- * \example
- * rev_fold<typelist<>, V, F> == V
- * \param List The list to fold
- * \param V The initial item fed to Fn
- * \param Fn The binary Invocable
- */
- template <typename List, typename V, typename Fn>
- using rev_fold = eval<
- rev_fold_impl::rev_fold_<List, V, Fn>
- >;
- //! @}
-
- /*!
- * Return a new \c typelist by adding the elements \p Ts to the front of \p List.
- * Complexity \f$ O(1) \f$
- */
- template <typename List, typename... Ts>
- using push_front = eval<
- apply <
- bind_front<quote<typelist>, Ts...>, List
- >
- >;
-
- /*!
- * Return a new \c typelist by adding the elements \p Ts to the back of \p List.
- * Complexity \f$ O(1) \f$
- */
- template <typename List, typename... Ts>
- using push_back = eval<
- apply <
- bind_back<quote<typelist>, Ts...>, List
- >
- >;
-
- //! reverse
- //! @{
- namespace reverse_impl {
-
- template <typename List, typename V = typelist<>>
- struct reverse_ {
- using type = fold<List, V, quote<push_front>>;
- };
- }
-
- /*!
- * Return a new \c typelist by reversing the elements in the list \p List.
- * Complexity \f$ O(N) \f$
- */
- template <typename List>
- using reverse = eval<
- reverse_impl::reverse_<List>
- >;
- //! @}
-
- //! pop_front
- //! @{
- namespace pop_front_impl {
- template <typename List>
- struct pop_front_ { };
-
- template <typename Head, typename... Tail>
- struct pop_front_<typelist <Head, Tail...>> {
- using type = typelist<Tail...>;
- };
- }
-
- /*!
- * Return a new \c typelist by removing the first element from the
- * front of \p List.
- * Complexity \f$ O(1) \f$
- */
- template <typename List>
- using pop_front = eval<
- pop_front_impl::pop_front_<List>
- >;
- //! @}
-
- //! pop_back
- //! @{
- namespace pop_back_impl {
- template <typename List>
- struct pop_back_ {
- using type = reverse<
- pop_front<reverse<List>>
- >;
- };
- }
-
- /*!
- * Return a new \c typelist by removing the last element from the \p List.
- * Complexity \f$ O(N) \f$.
- * \note
- * This operation, in addition from other push/pop operations, is
- * heavy(2 reverse operations).
- */
- template <typename List>
- using pop_back = eval <
- pop_back_impl::pop_back_<List>
- >;
- //! @}
-
- //! Transform
- //! @{
- namespace transform_impl {
- template <typename, typename = void>
- struct transform_ { };
-
- template <typename... Ts, typename Fn>
- struct transform_<typelist<typelist<Ts...>, Fn>,
- void_t<invoke<Fn, Ts>...> > /* SFINAE check */ {
- using type = typelist<
- invoke_t<Fn, Ts>...
- >;
- };
-
- template <typename... Ts0, typename... Ts1, typename Fn>
- struct transform_<typelist<typelist<Ts0...>, typelist<Ts1...>, Fn>,
- void_t<invoke<Fn, Ts0, Ts1>...>> /* SFINAE check */ {
- using type = typelist<
- invoke_t<Fn, Ts0, Ts1>...
- >;
- };
- }
-
- /*!
- * Transformation by applying an invocable \c Fn to one or two lists
- * and return the resulting typelist
- *
- * Complexity \f$ O(N) \f$.
- * \example
- * \code
- * using l1 = typelist<char, int, ...>;
- * using l2 = typelist<void, void, ...>;
- * using r1 = transform<l1, F1>; // F1, unary invocable
- * using r2 = transform<l1, l2, F2>; // F2, binary invocable
- * \endcode
- */
- template <typename... Args>
- using transform = eval<
- transform_impl::transform_<typelist<Args...>>
- >;
- //! @}
-
- //! Transform lazy
- //! @{
- namespace transform_lazy_impl {
- template <typename, typename = void>
- struct transform_lazy_ { };
-
- // Match for Unary Fn with one typelist
- template <typename... Ts, typename Fn>
- struct transform_lazy_<typelist<typelist<Ts...>, Fn>,
- void_t<invoke<Fn, Ts>...> > /* SFINAE check */ {
- using type = typelist<
- invoke<Fn, Ts>...
- >;
- };
-
- // Match for Binary Fn with two typelists
- template <typename... Ts0, typename... Ts1, typename Fn>
- struct transform_lazy_<typelist<typelist<Ts0...>, typelist<Ts1...>, Fn>,
- void_t<invoke<Fn, Ts0, Ts1>...>> /* SFINAE check */ {
- using type = typelist<
- invoke<Fn, Ts0, Ts1>...
- >;
- };
- }
-
- /*!
- * Transformation by applying an invocable \c Fn to one or two lists
- * and return a typelist containing the invocables with their arguments,
- * not their resulting types.
- *
- * Complexity \f$ O(N) \f$
- *
- * \example
- * \code
- * using l1 = typelist<char, int, ...>;
- * using l2 = typelist<void, void, ...>;
- * using r1 = transform<l1, F1>; // F1, unary invocable
- * using r2 = transform<l1, l2, F2>; // F2, binary invocable
- * \endcode
- */
- template <typename... Args>
- using transform_lazy = eval<
- transform_lazy_impl::transform_lazy_<typelist<Args...>>
- >;
- //! @}
-
-
- //! find_if, find
- //! @{
- namespace find_if_impl {
- template <typename, typename, index_t>
- struct find_if_ { };
-
- template<typename Head, typename... Tail, typename Fn, index_t N>
- struct find_if_<typelist<Head, Tail...>, Fn, N> {
- // Recursive call to find_if_ until Fn returns true_
- using type = if_ <
- invoke_t<Fn, Head>,
- index_<N>, // done, return current index
- eval<find_if_< // not done, re-call find_if_ with the Tail...
- typelist<Tail...>, Fn, N+1>
- >
- >;
- };
-
- // When empty or when we are one place after the last item return Npos
- template<typename Fn, index_t N>
- struct find_if_<typelist<>, Fn, N> {
- using type = Npos;
- };
- }
-
- /*!
- * Search for the first \c Item on the \p List for which the predicate \p Pred
- * returns true_ when `eval<invoke<Pred, Item>>`
- *
- * Complexity \f$ O(N) \f$
- *
- * \param List A typelist
- * \param Pred A Unary invocable predicate
- * \return An integral constant of index_t with the location of the first match,
- * or Npos otherwise.
- */
- template<typename List, typename Pred>
- using find_if = eval<
- find_if_impl::find_if_<List, Pred, 0>
- >;
-
- /*!
- * Search for the first occurrence of type \p T on a \p List
- */
- template <typename List, typename T>
- using find = find_if<List, same_as<T>>;
- //! @}
-
- //! seek_if
- //! @{
- namespace seek_if_impl {
- template <typename, typename, index_t>
- struct seek_if_ { };
-
- template<typename Head, typename... Tail, typename Fn, index_t N>
- struct seek_if_<typelist<Head, Tail...>, Fn, N> {
- // recursive call to seek_if_ until Fn returns true_
- using type = if_ <
- invoke_t<Fn, Head>,
- typelist<Head, Tail...>, // done, return the typelist starting from here
- eval<seek_if_< // not done, re-call seek_if_ with the Tail...
- typelist<Tail...>, Fn, N+1>
- >
- >;
- };
-
- // When empty or when we are one place after the last item return empty typelist
- template<typename Fn, index_t N>
- struct seek_if_<typelist<>, Fn, N> {
- using type = typelist<>;
- };
- }
-
- /*!
- * Search for the first \c Item on the \p List for which the predicate \p Pred
- * returns true_ when `eval<invoke<Pred, Item>>` and return the rest of the \p List
- * starting from that position as new typelist
- *
- * Complexity \f$ O(N) \f$
- *
- * \param List A typelist
- * \param Pred A Unary invocable predicate
- * \return An integral constant with the location of the first match, on Npos otherwise
- */
- template <typename List, typename Pred>
- using seek_if = eval<
- seek_if_impl::seek_if_<List, Pred, 0>
- >;
- /*!
- * Search for the first \c Item on the \p List of type \p T and return the rest
- * of the \p List starting from that position as new typelist
- */
- template <typename List, typename T>
- using seek = seek_if <List, same_as<T>>;
- //! @}
-
- //! count_if
- //! @{
- namespace count_if_impl {
- template <typename, typename, size_t>
- struct count_if_ { };
-
- template<typename Head, typename... Tail, typename Fn, size_t N>
- struct count_if_<typelist<Head, Tail...>, Fn, N> {
- // Recursive call to count_if_ up to the end of List, counting all invokes of Fn
- // returning true_
- using type = if_ <
- invoke_t<Fn, Head>,
- eval<
- count_if_<typelist<Tail...>, Fn, N+1> // increase and re-call
- >,
- eval<
- count_if_<typelist<Tail...>, Fn, N> // re-call without increasing
- >
- >;
- };
-
- // At the end of the List return the counter
- template<typename Fn, size_t N>
- struct count_if_<typelist<>, Fn, N> {
- using type = size_<N>;
- };
- }
-
- /*!
- * Count all \c Items on the \p List for which the predicate \p Pred
- * returns true_ when `eval<invoke<Pred, Item>>`
- *
- * Complexity \f$ O(N) \f$
- *
- * \param List A typelist
- * \param Pred A Unary invocable predicate
- * \return The total count of occurrences as an integral constant of size_t
- */
- template <typename List, typename Pred>
- using count_if = eval<
- count_if_impl::count_if_<List, Pred, 0>
- >;
-
- /*!
- * Count all occurrences of type \p T int \p List
- */
- template <typename List, typename T>
- using count = count_if<List, same_as<T>>;
- //! @}
-
- //! filter
- //! @{
- namespace filter_impl {
- template <typename, typename, typename>
- struct filter_ { };
-
- template<typename Head, typename... Tail, typename Fn, typename L>
- struct filter_<typelist<Head, Tail...>, Fn, L> {
- // Recursive call to filter_ up to the end of the List, creating a new list
- // of items for which the invoke of Fn returns true_
- using type = if_ <
- invoke_t <Fn, Head>,
- eval<filter_<typelist<Tail...>, Fn, cat<L, typelist<Head>>>>, // Add the element and re-call
- eval<filter_<typelist<Tail...>, Fn, L>> // re-call with the same list
- >;
- };
-
- // At the end return the produced list
- template<typename Fn, typename L>
- struct filter_<typelist<>, Fn, L> {
- using type = L;
- };
- }
-
- /*!
- * Return a new typelist with elements, the elements of \p List that satisfy the
- * invocable \p Pred such that `eval<invoke<Pred, Item>>` is \c true_
- *
- * Complexity \f$ O(N) \f$
- *
- * \param List The input typelist
- * \param Pred A unary invocable predicate
- */
- template <typename List, typename Pred>
- using filter = eval<
- filter_impl::filter_<List, Pred, typelist<>>
- >;
- //! @}
-
- //! replace
- //! @{
- namespace replace_if_impl {
- template <typename, typename, typename, typename>
- struct replace_if_ { };
-
- template <typename Head, typename... Tail, typename Fn, typename T, typename Ret>
- struct replace_if_<typelist<Head, Tail...>, Fn, T, Ret> {
- // Recursive call to replace_if_ up to the end of the List, creating a new list
- // of items based on invocation of Fn
- using type = if_ <
- invoke_t<Fn, Head>,
- eval<replace_if_<typelist<Tail...>, Fn, T, cat<Ret, typelist<T>>>>, // re-call with change to T
- eval<replace_if_<typelist<Tail...>, Fn, T, cat<Ret, typelist<Head>>>> // re-call with no change
- >;
- };
-
- // At the end return the produced list
- template <typename Fn, typename T, typename Ret>
- struct replace_if_ <typelist<>, Fn, T, Ret> {
- using type = Ret;
- };
- }
-
- /*!
- * Return a new typelist where all the instances for which the invocation of\p Pred
- * returns \c true_, are replaced with \p T
- *
- * Complexity \f$ O(N) \f$
- *
- * \param List The input typelist
- * \param Pred A unary invocable predicate
- * \param T The new type to replace the item of the \p List, when eval<invoke<Pred, Item>>
- * returns \c true_
- */
- template<typename List, typename Pred, typename T>
- using replace_if = eval<
- replace_if_impl::replace_if_<List, Pred, T, typelist<>>
- >;
-
- //! Alias wrapper that returns a new \c typelist where all instances of type \p T have
- //! been replaced with \p U.
- template <typename List, typename T, typename U>
- using replace = eval <
- replace_if <List, same_as<T>, U>
- >;
- //! @}
-
-
- //! Returns \c true_ if \p Pred returns \c true_ for all the elements in the \p List or if the
- //! \p List is empty and \c false_ otherwise.
- template <typename List, typename Pred>
- using all_of = empty<
- filter <List, compose<quote<not_>, Pred>>
- >;
-
- //! Returns \c true_ if \p Pred returns \c true_ for any of the elements in the \p List
- //! and \c false_ otherwise.
- template <typename List, typename Pred>
- using any_of = not_<
- empty<filter <List, Pred>>
- >;
-
- //! Returns \c true_ if \p Pred returns \c false_ for all the elements in the \p List
- //! or if the \p List is empty and \c false otherwise.
- template <typename List, typename Pred>
- using none_of = empty<
- filter <List, Pred>
- >;
-
- }}
-
- //! @}
- #endif /* __utl_meta_pack_h__ */
|