SpECTRE Documentation Coverage Report
Current view: top level - Utilities - TMPL.hpp Hit Total Coverage
Commit: b5f497991094937944b0a3f519166bb54739d08a Lines: 16 49 32.7 %
Date: 2024-03-28 18:20:13
Legend: Lines: hit not hit

          Line data    Source code
       1           1 : // Distributed under the MIT License.
       2             : // See LICENSE.txt for details.
       3             : 
       4             : /// \file
       5             : /// Wraps the template metaprogramming library used (brigand)
       6             : 
       7             : #pragma once
       8             : 
       9             : // Since this header only wraps brigand and several additions to it we mark
      10             : // it as a system header file so that clang-tidy ignores it.
      11             : #ifdef __GNUC__
      12             : #pragma GCC system_header
      13             : #endif
      14             : 
      15             : /// \cond NEVER
      16             : #define BRIGAND_NO_BOOST_SUPPORT
      17             : /// \endcond
      18             : #include <brigand/brigand.hpp>
      19             : 
      20             : #include <cstddef>
      21             : #include <initializer_list>  // IWYU pragma: keep
      22             : #include <type_traits>
      23             : #include <variant>
      24             : 
      25             : #include "Utilities/TmplDigraph.hpp"  // IWYU pragma: export
      26             : 
      27           0 : namespace brigand {
      28             : /// \cond
      29             : namespace detail {
      30             : 
      31             : // specializations to catch attempts to transform a non-sequence
      32             : template <typename NotSeq, class Func>
      33             : struct transform<0, NotSeq, Func> {
      34             :   static_assert(
      35             :       std::is_same_v<list<>, NotSeq>,
      36             :       "Cannot transform a non-sequence (the second argument of is_same_v).");
      37             :   using type = std::void_t<>;
      38             : };
      39             : 
      40             : template <typename NotSeq, template <class...> class Seq, class... T,
      41             :           class Func>
      42             : struct transform<1, NotSeq, Seq<T...>, Func> {
      43             :   static_assert(
      44             :       std::is_same_v<list<>, NotSeq>,
      45             :       "Cannot transform a non-sequence (the second argument of is_same_v).");
      46             :   using type = std::void_t<>;
      47             : };
      48             : 
      49             : template <template <class...> class Seq, class... T, typename NotSeq,
      50             :           class Func>
      51             : struct transform<1, Seq<T...>, NotSeq, Func> {
      52             :   static_assert(
      53             :       std::is_same_v<list<>, NotSeq>,
      54             :       "Cannot transform a non-sequence (the second argument of is_same_v).");
      55             :   using type = std::void_t<>;
      56             : };
      57             : 
      58             : template <typename NotSeq1, typename NotSeq2, class Func>
      59             : struct transform<1, NotSeq1, NotSeq2, Func> {
      60             :   static_assert(
      61             :       std::is_same_v<list<>, NotSeq1>,
      62             :       "Cannot transform a non-sequence (the second argument of is_same_v).");
      63             :   using type = std::void_t<>;
      64             : };
      65             : 
      66             : template <bool b, typename O, typename L, std::size_t I, typename R,
      67             :           typename U = void>
      68             : struct replace_at_impl;
      69             : 
      70             : template <template <typename...> class S, typename... Os, typename... Ts,
      71             :           typename R>
      72             : struct replace_at_impl<false, S<Os...>, S<Ts...>, 0, R> {
      73             :   using type = S<Os..., Ts...>;
      74             : };
      75             : 
      76             : template <template <typename...> class S, typename... Os, typename... Ts,
      77             :           typename T, typename R>
      78             : struct replace_at_impl<false, S<Os...>, S<T, Ts...>, 1, R>
      79             :     : replace_at_impl<false, S<Os..., R>, S<Ts...>, 0, R> {};
      80             : 
      81             : template <template <typename...> class S, typename... Os, typename T,
      82             :           typename... Ts, std::size_t I, typename R>
      83             : struct replace_at_impl<false, S<Os...>, S<T, Ts...>, I, R,
      84             :                        typename std::enable_if<(I > 1)>::type>
      85             :     : replace_at_impl<false, S<Os..., T>, S<Ts...>, (I - 1), R> {};
      86             : 
      87             : template <template <typename...> class S, typename... Os, typename T1,
      88             :           typename T2, typename T3, typename T4, typename T5, typename T6,
      89             :           typename T7, typename T8, typename T9, typename T10, typename T11,
      90             :           typename T12, typename T13, typename T14, typename T15, typename T16,
      91             :           typename... Ts, std::size_t I, typename R>
      92             : struct replace_at_impl<true, S<Os...>,
      93             :                        S<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
      94             :                          T14, T15, T16, Ts...>,
      95             :                        I, R>
      96             :     : replace_at_impl<((I - 16) > 16),
      97             :                       S<Os..., T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
      98             :                         T12, T13, T14, T15, T16>,
      99             :                       S<Ts...>, (I - 16), R> {};
     100             : 
     101             : template <typename L, typename I, typename R>
     102             : struct call_replace_at_impl
     103             :     : replace_at_impl<(I::value > 15), brigand::clear<L>, L, I::value + 1, R> {
     104             : };
     105             : }  // namespace detail
     106             : /// \endcond
     107             : 
     108           0 : namespace lazy {
     109             : template <typename L, typename I, typename R>
     110           0 : using replace_at = ::brigand::detail::call_replace_at_impl<L, I, R>;
     111             : }  // namespace lazy
     112             : template <typename L, typename I, typename R>
     113           0 : using replace_at = typename ::brigand::lazy::replace_at<L, I, R>::type;
     114             : }  // namespace brigand
     115             : 
     116             : namespace brigand {
     117             : namespace detail {
     118             : template <typename List, typename Ind1, typename Ind2>
     119             : struct swap_at_impl {
     120             :   using type = ::brigand::replace_at<
     121             :       ::brigand::replace_at<List, Ind1, ::brigand::at<List, Ind2>>, Ind2,
     122             :       ::brigand::at<List, Ind1>>;
     123             : };
     124             : }  // namespace detail
     125             : 
     126             : template <typename List, typename Ind1, typename Ind2>
     127           0 : using swap_at =
     128             :     typename ::brigand::detail::swap_at_impl<List, Ind1, Ind2>::type;
     129             : }  // namespace brigand
     130             : 
     131             : namespace brigand {
     132             : template <typename V>
     133           0 : using abs = std::integral_constant<typename V::value_type,
     134             :                                    (V::value < 0 ? -V::value : V::value)>;
     135             : 
     136             : template <typename V>
     137           0 : using sign =
     138             :     std::integral_constant<typename V::value_type, (V::value < 0 ? -1 : 1)>;
     139             : 
     140             : template <int T>
     141           0 : using int_ = std::integral_constant<int, T>;
     142             : 
     143             : template <typename V, typename N>
     144           0 : struct power
     145             :     : std::integral_constant<
     146             :           typename V::value_type,
     147             :           V::value * power<V, std::integral_constant<typename N::value_type,
     148             :                                                      N::value - 1>>::value> {};
     149             : 
     150             : template <typename V, typename T>
     151             : struct power<V, std::integral_constant<T, 0>>
     152             :     : std::integral_constant<typename V::value_type, 1> {};
     153             : 
     154             : template <typename T>
     155           0 : struct factorial : times<T, factorial<uint64_t<T::value - 1>>> {};
     156             : template <>
     157           0 : struct factorial<uint64_t<1>> : uint64_t<1> {};
     158             : }  // namespace brigand
     159             : 
     160             : namespace brigand {
     161             : namespace detail {
     162             : template <typename List, std::size_t Size = size<List>::value>
     163             : struct permutations_impl {
     164             :   template <typename T, typename List1>
     165             :   struct helper {
     166             :     using type = ::brigand::transform<
     167             :         typename permutations_impl<::brigand::remove<List1, T>>::type,
     168             :         ::brigand::lazy::push_front<_state, T>>;
     169             :   };
     170             : 
     171             :   using type = ::brigand::fold<
     172             :       List, list<>,
     173             :       ::brigand::lazy::append<::brigand::_state, helper<::brigand::_element,
     174             :                                                         ::brigand::pin<List>>>>;
     175             : };
     176             : 
     177             : template <typename List>
     178             : struct permutations_impl<List, 1> {
     179             :   using type = list<List>;
     180             : };
     181             : }  // namespace detail
     182             : 
     183             : namespace lazy {
     184             : template <typename List>
     185           0 : using permutations = detail::permutations_impl<List>;
     186             : }  // namespace lazy
     187             : 
     188             : template <typename List>
     189           0 : using permutations = typename lazy::permutations<List>::type;
     190             : }  // namespace brigand
     191             : 
     192             : namespace brigand {
     193             : namespace detail {
     194             : template <typename List, std::size_t Size = ::brigand::size<List>::value>
     195             : struct generic_permutations_impl {
     196             :   template <typename Lc, typename List1>
     197             :   struct helper {
     198             :     using type = ::brigand::transform<
     199             :         typename generic_permutations_impl<::brigand::erase<List1, Lc>>::type,
     200             :         ::brigand::lazy::push_front<::brigand::_state,
     201             :                                     ::brigand::at<List1, Lc>>>;
     202             :   };
     203             :   using type = ::brigand::fold<
     204             :       ::brigand::make_sequence<brigand::uint32_t<0>, Size>, ::brigand::list<>,
     205             :       ::brigand::lazy::append<::brigand::_state, helper<::brigand::_element,
     206             :                                                         ::brigand::pin<List>>>>;
     207             : };
     208             : 
     209             : template <typename List>
     210             : struct generic_permutations_impl<List, 1> {
     211             :   using type = ::brigand::list<List>;
     212             : };
     213             : }  // namespace detail
     214             : 
     215             : namespace lazy {
     216             : template <typename List>
     217           0 : using generic_permutations = detail::generic_permutations_impl<List>;
     218             : }  // namespace lazy
     219             : 
     220             : template <typename List>
     221           0 : using generic_permutations = typename lazy::generic_permutations<List>::type;
     222             : }  // namespace brigand
     223             : 
     224             : namespace brigand {
     225             : namespace detail {
     226             : template <typename List, typename Number = uint32_t<1>>
     227             : struct combinations_impl_helper {
     228             :   using split_list = split_at<List, Number>;
     229             :   using type =
     230             :       fold<back<split_list>, list<>,
     231             :            lazy::append<
     232             :                _state,
     233             :                bind<list, bind<push_back, pin<front<split_list>>, _element>>>>;
     234             : };
     235             : 
     236             : template <typename List, typename OutSize, typename = void>
     237             : struct combinations_impl {
     238             :   using type =
     239             :       append<list<>,
     240             :              typename combinations_impl_helper<List, prev<OutSize>>::type,
     241             :              typename combinations_impl<pop_front<List>, OutSize>::type>;
     242             : };
     243             : template <typename List, typename OutSize>
     244             : struct combinations_impl<
     245             :     List, OutSize,
     246             :     typename std::enable_if<OutSize::value == size<List>::value>::type> {
     247             :   using type = typename combinations_impl_helper<List, prev<OutSize>>::type;
     248             : };
     249             : }  // namespace detail
     250             : 
     251             : namespace lazy {
     252             : template <typename List, typename OutSize = uint32_t<2>>
     253           0 : using combinations = detail::combinations_impl<List, OutSize>;
     254             : }  // namespace lazy
     255             : 
     256             : template <typename List, typename OutSize = uint32_t<2>>
     257           0 : using combinations = typename lazy::combinations<List, OutSize>::type;
     258             : }  // namespace brigand
     259             : 
     260             : namespace brigand {
     261             : namespace detail {
     262             : template <typename Seq, typename T>
     263             : struct equal_members_helper
     264             :     : std::is_same<count_if<Seq, std::is_same<T, _1>>, size_t<1>> {};
     265             : }  // namespace detail
     266             : 
     267             : template <typename List1, typename List2>
     268           0 : using equal_members = and_<
     269             :     fold<List1, bool_<true>,
     270             :          and_<_state, detail::equal_members_helper<pin<List2>, _element>>>,
     271             :     fold<List2, bool_<true>,
     272             :          and_<_state, detail::equal_members_helper<pin<List1>, _element>>>>;
     273             : }  // namespace brigand
     274             : 
     275             : namespace brigand {
     276             : namespace detail {
     277             : template <typename Functor, typename State, typename I, typename Sequence>
     278             : struct enumerated_fold_impl {
     279             :   using type = State;
     280             : };
     281             : 
     282             : template <typename Functor, typename State, typename I,
     283             :           template <typename...> class Sequence, typename T0>
     284             : struct enumerated_fold_impl<Functor, State, I, Sequence<T0>> {
     285             :   using type = brigand::apply<Functor, State, T0, I>;
     286             : };
     287             : 
     288             : template <typename Functor, typename State, typename I,
     289             :           template <typename...> class Sequence, typename T0, typename T1>
     290             : struct enumerated_fold_impl<Functor, State, I, Sequence<T0, T1>> {
     291             :   using type = brigand::apply<Functor, brigand::apply<Functor, State, T0, I>,
     292             :                               T1, brigand::next<I>>;
     293             : };
     294             : 
     295             : template <typename Functor, typename State, typename I,
     296             :           template <typename...> class Sequence, typename T0, typename T1,
     297             :           typename T2>
     298             : struct enumerated_fold_impl<Functor, State, I, Sequence<T0, T1, T2>> {
     299             :   using type = brigand::apply<
     300             :       Functor,
     301             :       brigand::apply<Functor, brigand::apply<Functor, State, T0, I>, T1,
     302             :                      brigand::next<I>>,
     303             :       T2, brigand::plus<I, brigand::int32_t<2>>>;
     304             : };
     305             : 
     306             : template <typename Functor, typename State, typename I,
     307             :           template <typename...> class Sequence, typename T0, typename T1,
     308             :           typename T2, typename T3>
     309             : struct enumerated_fold_impl<Functor, State, I, Sequence<T0, T1, T2, T3>> {
     310             :   using type = brigand::apply<
     311             :       Functor,
     312             :       brigand::apply<
     313             :           Functor,
     314             :           brigand::apply<Functor, brigand::apply<Functor, State, T0, I>, T1,
     315             :                          brigand::next<I>>,
     316             :           T2, brigand::plus<I, brigand::int32_t<2>>>,
     317             :       T3, brigand::plus<I, brigand::int32_t<3>>>;
     318             : };
     319             : 
     320             : template <typename Functor, typename State, typename I,
     321             :           template <typename...> class Sequence, typename T0, typename T1,
     322             :           typename T2, typename T3, typename T4>
     323             : struct enumerated_fold_impl<Functor, State, I, Sequence<T0, T1, T2, T3, T4>> {
     324             :   using type = brigand::apply<
     325             :       Functor,
     326             :       brigand::apply<
     327             :           Functor,
     328             :           brigand::apply<
     329             :               Functor,
     330             :               brigand::apply<Functor, brigand::apply<Functor, State, T0, I>, T1,
     331             :                              brigand::next<I>>,
     332             :               T2, brigand::plus<I, brigand::int32_t<2>>>,
     333             :           T3, brigand::plus<I, brigand::int32_t<3>>>,
     334             :       T4, brigand::plus<I, brigand::int32_t<4>>>;
     335             : };
     336             : 
     337             : template <typename Functor, typename State, typename I,
     338             :           template <typename...> class Sequence, typename T0, typename T1,
     339             :           typename T2, typename T3, typename T4, typename T5>
     340             : struct enumerated_fold_impl<Functor, State, I,
     341             :                             Sequence<T0, T1, T2, T3, T4, T5>> {
     342             :   using type = brigand::apply<
     343             :       Functor,
     344             :       brigand::apply<
     345             :           Functor,
     346             :           brigand::apply<
     347             :               Functor,
     348             :               brigand::apply<
     349             :                   Functor,
     350             :                   brigand::apply<Functor, brigand::apply<Functor, State, T0, I>,
     351             :                                  T1, brigand::next<I>>,
     352             :                   T2, brigand::plus<I, brigand::int32_t<2>>>,
     353             :               T3, brigand::plus<I, brigand::int32_t<3>>>,
     354             :           T4, brigand::plus<I, brigand::int32_t<4>>>,
     355             :       T5, brigand::plus<I, brigand::int32_t<5>>>;
     356             : };
     357             : 
     358             : template <typename Functor, typename State, typename I,
     359             :           template <typename...> class Sequence, typename T0, typename T1,
     360             :           typename T2, typename T3, typename T4, typename T5, typename T6>
     361             : struct enumerated_fold_impl<Functor, State, I,
     362             :                             Sequence<T0, T1, T2, T3, T4, T5, T6>> {
     363             :   using type = brigand::apply<
     364             :       Functor,
     365             :       brigand::apply<
     366             :           Functor,
     367             :           brigand::apply<
     368             :               Functor,
     369             :               brigand::apply<
     370             :                   Functor,
     371             :                   brigand::apply<
     372             :                       Functor,
     373             :                       brigand::apply<Functor,
     374             :                                      brigand::apply<Functor, State, T0, I>, T1,
     375             :                                      brigand::next<I>>,
     376             :                       T2, brigand::plus<I, brigand::int32_t<2>>>,
     377             :                   T3, brigand::plus<I, brigand::int32_t<3>>>,
     378             :               T4, brigand::plus<I, brigand::int32_t<4>>>,
     379             :           T5, brigand::plus<I, brigand::int32_t<5>>>,
     380             :       T6, brigand::plus<I, brigand::int32_t<6>>>;
     381             : };
     382             : 
     383             : template <typename Functor, typename State, typename I,
     384             :           template <typename...> class Sequence, typename T0, typename T1,
     385             :           typename T2, typename T3, typename T4, typename T5, typename T6,
     386             :           typename T7>
     387             : struct enumerated_fold_impl<Functor, State, I,
     388             :                             Sequence<T0, T1, T2, T3, T4, T5, T6, T7>> {
     389             :   using type = brigand::apply<
     390             :       Functor,
     391             :       brigand::apply<
     392             :           Functor,
     393             :           brigand::apply<
     394             :               Functor,
     395             :               brigand::apply<
     396             :                   Functor,
     397             :                   brigand::apply<
     398             :                       Functor,
     399             :                       brigand::apply<
     400             :                           Functor,
     401             :                           brigand::apply<Functor,
     402             :                                          brigand::apply<Functor, State, T0, I>,
     403             :                                          T1, brigand::next<I>>,
     404             :                           T2, brigand::plus<I, brigand::int32_t<2>>>,
     405             :                       T3, brigand::plus<I, brigand::int32_t<3>>>,
     406             :                   T4, brigand::plus<I, brigand::int32_t<4>>>,
     407             :               T5, brigand::plus<I, brigand::int32_t<5>>>,
     408             :           T6, brigand::plus<I, brigand::int32_t<6>>>,
     409             :       T7, brigand::plus<I, brigand::int32_t<7>>>;
     410             : };
     411             : 
     412             : template <typename Functor, typename State, typename I,
     413             :           template <typename...> class Sequence, typename T0, typename T1,
     414             :           typename T2, typename T3, typename T4, typename T5, typename T6,
     415             :           typename T7, typename... T>
     416             : struct enumerated_fold_impl<Functor, State, I,
     417             :                             Sequence<T0, T1, T2, T3, T4, T5, T6, T7, T...>>
     418             :     : enumerated_fold_impl<
     419             :           Functor,
     420             :           brigand::apply<
     421             :               Functor,
     422             :               brigand::apply<
     423             :                   Functor,
     424             :                   brigand::apply<
     425             :                       Functor,
     426             :                       brigand::apply<
     427             :                           Functor,
     428             :                           brigand::apply<
     429             :                               Functor,
     430             :                               brigand::apply<
     431             :                                   Functor,
     432             :                                   brigand::apply<
     433             :                                       Functor,
     434             :                                       brigand::apply<Functor, State, T0, I>, T1,
     435             :                                       brigand::next<I>>,
     436             :                                   T2, brigand::plus<I, brigand::int32_t<2>>>,
     437             :                               T3, brigand::plus<I, brigand::int32_t<3>>>,
     438             :                           T4, brigand::plus<I, brigand::int32_t<4>>>,
     439             :                       T5, brigand::plus<I, brigand::int32_t<5>>>,
     440             :                   T6, brigand::plus<I, brigand::int32_t<6>>>,
     441             :               T7, brigand::plus<I, brigand::int32_t<7>>>,
     442             :           brigand::plus<I, brigand::int32_t<8>>, Sequence<T...>> {};
     443             : }  // namespace detail
     444             : 
     445             : namespace lazy {
     446             : template <typename Sequence, typename State, typename Functor,
     447             :           typename I = brigand::int32_t<0>>
     448           0 : using enumerated_fold =
     449             :     typename detail::enumerated_fold_impl<Functor, State, I, Sequence>;
     450             : }  // namespace lazy
     451             : 
     452             : template <typename Sequence, typename State, typename Functor,
     453             :           typename I = brigand::int32_t<0>>
     454           0 : using enumerated_fold =
     455             :     typename lazy::enumerated_fold<Sequence, State, Functor, I>::type;
     456             : }  // namespace brigand
     457             : 
     458             : namespace brigand {
     459             : template <bool>
     460           0 : struct conditional;
     461             : 
     462             : template <>
     463           0 : struct conditional<true> {
     464             :   template <typename T, typename F>
     465           0 :   using type = T;
     466             : };
     467             : 
     468             : template <>
     469           0 : struct conditional<false> {
     470             :   template <typename T, typename F>
     471           0 :   using type = F;
     472             : };
     473             : 
     474             : template <bool B, typename T, typename F>
     475           0 : using conditional_t = typename conditional<B>::template type<T, F>;
     476             : }  // namespace brigand
     477             : 
     478             : namespace brigand {
     479             : template <typename List>
     480           0 : using remove_duplicates =
     481             :     fold<List, clear<List>,
     482             :          if_<bind<none, _state, defer<std::is_same<_1, parent<_element>>>>,
     483             :              bind<push_back, _state, _element>, _state>>;
     484             : }  // namespace brigand
     485             : 
     486             : namespace brigand {
     487             : template <bool>
     488           0 : struct branch_if;
     489             : 
     490             : template <>
     491           0 : struct branch_if<true> {
     492             :   template <typename T, typename F>
     493           0 :   using type = typename detail::apply<T>::type;
     494             : };
     495             : 
     496             : template <>
     497           0 : struct branch_if<false> {
     498             :   template <typename T, typename F>
     499           0 :   using type = typename detail::apply<F>::type;
     500             : };
     501             : 
     502             : template <bool B, typename T, typename F>
     503           0 : using branch_if_t = typename branch_if<B>::template type<T, F>;
     504             : }  // namespace brigand
     505             : 
     506             : namespace tmpl = brigand;
     507             : 
     508             : /*!
     509             :  * \ingroup UtilitiesGroup
     510             :  * \brief Metaprogramming things that are not planned to be submitted to Brigand
     511             :  */
     512           1 : namespace tmpl2 {
     513             : /*!
     514             :  * \ingroup UtilitiesGroup
     515             :  * \brief A compile-time list of values of the same type
     516             :  */
     517             : template <class T, T...>
     518           1 : struct value_list {};
     519             : 
     520             : /*!
     521             :  * \ingroup UtilitiesGroup
     522             :  * \brief A non-short-circuiting logical AND between bools 'B""
     523             :  *
     524             :  * Useful when arbitrarily large parameter packs need to be evaluated, since
     525             :  * std::conjunction and std::disjunction use recursion
     526             :  */
     527             : template <bool... Bs>
     528           1 : using flat_all =
     529             :     std::is_same<value_list<bool, Bs...>,
     530             :                  value_list<bool, (static_cast<void>(Bs), true)...>>;
     531             : 
     532             : /*!
     533             :  * \ingroup UtilitiesGroup
     534             :  * \brief A non-short-circuiting logical AND between bools 'B""
     535             :  *
     536             :  * Useful when arbitrarily large parameter packs need to be evaluated, since
     537             :  * std::conjunction and std::disjunction use recursion
     538             :  */
     539             : template <bool... Bs>
     540           1 : constexpr bool flat_all_v = flat_all<Bs...>::value;
     541             : 
     542             : /*!
     543             :  * \ingroup UtilitiesGroup
     544             :  * \brief A non-short-circuiting logical OR between bools 'B""
     545             :  *
     546             :  * Useful when arbitrarily large parameter packs need to be evaluated, since
     547             :  * std::conjunction and std::disjunction use recursion
     548             :  */
     549             : template <bool... Bs>
     550           1 : using flat_any = std::integral_constant<
     551             :     bool, not std::is_same<
     552             :               value_list<bool, Bs...>,
     553             :               value_list<bool, (static_cast<void>(Bs), false)...>>::value>;
     554             : 
     555             : /*!
     556             :  * \ingroup UtilitiesGroup
     557             :  * \brief A non-short-circuiting logical OR between bools 'B""
     558             :  *
     559             :  * Useful when arbitrarily large parameter packs need to be evaluated, since
     560             :  * std::conjunction and std::disjunction use recursion
     561             :  */
     562             : template <bool... Bs>
     563           1 : constexpr bool flat_any_v = flat_any<Bs...>::value;
     564             : }  // namespace tmpl2
     565             : 
     566             : /*!
     567             :  * \ingroup UtilitiesGroup
     568             :  * \brief Allows zero-cost unordered expansion of a parameter
     569             :  *
     570             :  * \details
     571             :  * Expands a parameter pack, typically useful for runtime evaluation via a
     572             :  * Callable such as a lambda, function, or function object. For example,
     573             :  * an unordered transform of a std::tuple can be implemented as:
     574             :  * \snippet Utilities/Test_TMPL.cpp expand_pack_example
     575             :  *
     576             :  * \see tuple_fold tuple_counted_fold tuple_transform std::tuple
     577             :  * EXPAND_PACK_LEFT_TO_RIGHT
     578             :  */
     579             : template <typename... Ts>
     580           1 : constexpr void expand_pack(Ts&&... /*unused*/) {}
     581             : 
     582             : /*!
     583             :  * \ingroup UtilitiesGroup
     584             :  * \brief Expand a parameter pack evaluating the terms from left to right.
     585             :  *
     586             :  * The parameter pack inside the argument to the macro must not be expanded
     587             :  * since the macro will do the expansion correctly for you. In the below example
     588             :  * a parameter pack of `std::integral_constant<size_t, I>` is passed to the
     589             :  * function. The closure `lambda` is used to sum up the values of all the `Ts`.
     590             :  * Note that the `Ts` passed to `EXPAND_PACK_LEFT_TO_RIGHT` is not expanded.
     591             :  *
     592             :  * \snippet Utilities/Test_TMPL.cpp expand_pack_left_to_right
     593             :  *
     594             :  * \see tuple_fold tuple_counted_fold tuple_transform std::tuple expand_pack
     595             :  */
     596           1 : #define EXPAND_PACK_LEFT_TO_RIGHT(...) \
     597             :   (void)std::initializer_list<char> { ((void)(__VA_ARGS__), '0')... }
     598             : 
     599             : /*!
     600             :  * \ingroup UtilitiesGroup
     601             :  * \brief Returns the first argument of a parameter pack
     602             :  */
     603             : template <typename T, typename... Ts>
     604           1 : constexpr decltype(auto) get_first_argument(T&& t, Ts&&... /*rest*/) {
     605             :   return t;
     606             : }
     607             : 
     608             : namespace brigand {
     609             : namespace lazy {
     610             : /// Check if a typelist contains an item.
     611             : template <typename Sequence, typename Item>
     612           1 : struct list_contains;
     613             : 
     614             : /// \cond
     615             : template <template <typename...> typename L, typename... Items, typename Item>
     616             : struct list_contains<L<Items...>, Item>
     617             :     : bool_<(... or std::is_same_v<Items, Item>)> {};
     618             : /// \endcond
     619             : }  // namespace lazy
     620             : 
     621             : /// Check if a typelist contains an item.
     622             : /// @{
     623             : template <typename Sequence, typename Item>
     624           1 : using list_contains = typename lazy::list_contains<Sequence, Item>::type;
     625             : 
     626             : template <typename Sequence, typename Item>
     627           1 : constexpr bool list_contains_v = lazy::list_contains<Sequence, Item>::value;
     628             : /// @}
     629             : 
     630             : /// Obtain the elements of `Sequence1` that are not in `Sequence2`.
     631             : template <typename Sequence1, typename Sequence2>
     632           1 : using list_difference =
     633             :     fold<Sequence2, Sequence1, lazy::remove<_state, _element>>;
     634             : 
     635             : namespace detail {
     636             : template <typename List>
     637             : struct as_pack_impl;
     638             : 
     639             : template <template <typename...> typename L, typename... Args>
     640             : struct as_pack_impl<L<Args...>> {
     641             :   template <typename F>
     642             :   static constexpr decltype(auto) apply(F&& f) {
     643             :     return std::forward<F>(f)(type_<Args>{}...);
     644             :   }
     645             : };
     646             : }  // namespace detail
     647             : 
     648             : /// Call a functor with the types from a list.
     649             : ///
     650             : /// Given a typelist `List = tmpl::list<A, B, ...>` (not necessarily
     651             : /// with head `tmpl::list`), calls \p f as `f(tmpl::type_<A>{},
     652             : /// tmpl::type_<B>{}, ...)` and returns the result.
     653             : ///
     654             : /// This is useful for converting a typelist into a parameter pack.
     655             : ///
     656             : /// \snippet Utilities/Test_TMPL.cpp as_pack
     657             : template <typename List, typename F>
     658           1 : constexpr decltype(auto) as_pack(F&& f) {
     659             :   return detail::as_pack_impl<List>::apply(std::forward<F>(f));
     660             : }
     661             : 
     662             : namespace detail {
     663             : template <typename Sequence>
     664             : struct make_std_variant_over_impl;
     665             : 
     666             : template <template <typename...> class Sequence, typename... Ts>
     667             : struct make_std_variant_over_impl<Sequence<Ts...>> {
     668             :   static_assert(((not std::is_same_v<std::decay_t<std::remove_pointer_t<Ts>>,
     669             :                                      void>)&&...),
     670             :                 "Cannot create a std::variant with a 'void' type.");
     671             :   using type = std::variant<Ts...>;
     672             : };
     673             : }  // namespace detail
     674             : 
     675             : /*!
     676             :  * \ingroup UtilitiesGroup
     677             :  * \brief Create a std::variant with all all the types inside the typelist
     678             :  * Sequence
     679             :  *
     680             :  * \metareturns std::variant of all types inside `Sequence`
     681             :  */
     682             : template <typename Sequence>
     683           1 : using make_std_variant_over = typename detail::make_std_variant_over_impl<
     684             :     tmpl::remove_duplicates<Sequence>>::type;
     685             : }  // namespace brigand

Generated by: LCOV version 1.14