SpECTRE Documentation Coverage Report
Current view: top level - Utilities - TMPL.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 32.7 % 49 16
Test Date: 2026-10-22 17:29:42
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>
      22              : #include <type_traits>
      23              : #include <variant>
      24              : 
      25              : #include "Utilities/TmplDigraph.hpp"
      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 <bool>
     480            0 : struct branch_if;
     481              : 
     482              : template <>
     483            0 : struct branch_if<true> {
     484              :   template <typename T, typename F>
     485            0 :   using type = typename detail::apply<T>::type;
     486              : };
     487              : 
     488              : template <>
     489            0 : struct branch_if<false> {
     490              :   template <typename T, typename F>
     491            0 :   using type = typename detail::apply<F>::type;
     492              : };
     493              : 
     494              : template <bool B, typename T, typename F>
     495            0 : using branch_if_t = typename branch_if<B>::template type<T, F>;
     496              : }  // namespace brigand
     497              : 
     498              : namespace tmpl = brigand;
     499              : 
     500              : /*!
     501              :  * \ingroup UtilitiesGroup
     502              :  * \brief Metaprogramming things that are not planned to be submitted to Brigand
     503              :  */
     504            1 : namespace tmpl2 {
     505              : /*!
     506              :  * \ingroup UtilitiesGroup
     507              :  * \brief A compile-time list of values of the same type
     508              :  */
     509              : template <class T, T...>
     510            1 : struct value_list {};
     511              : 
     512              : /*!
     513              :  * \ingroup UtilitiesGroup
     514              :  * \brief A non-short-circuiting logical AND between bools 'B""
     515              :  *
     516              :  * Useful when arbitrarily large parameter packs need to be evaluated, since
     517              :  * std::conjunction and std::disjunction use recursion
     518              :  */
     519              : template <bool... Bs>
     520            1 : using flat_all =
     521              :     std::is_same<value_list<bool, Bs...>,
     522              :                  value_list<bool, (static_cast<void>(Bs), true)...>>;
     523              : 
     524              : /*!
     525              :  * \ingroup UtilitiesGroup
     526              :  * \brief A non-short-circuiting logical AND between bools 'B""
     527              :  *
     528              :  * Useful when arbitrarily large parameter packs need to be evaluated, since
     529              :  * std::conjunction and std::disjunction use recursion
     530              :  */
     531              : template <bool... Bs>
     532            1 : constexpr bool flat_all_v = flat_all<Bs...>::value;
     533              : 
     534              : /*!
     535              :  * \ingroup UtilitiesGroup
     536              :  * \brief A non-short-circuiting logical OR between bools 'B""
     537              :  *
     538              :  * Useful when arbitrarily large parameter packs need to be evaluated, since
     539              :  * std::conjunction and std::disjunction use recursion
     540              :  */
     541              : template <bool... Bs>
     542            1 : using flat_any = std::integral_constant<
     543              :     bool, not std::is_same<
     544              :               value_list<bool, Bs...>,
     545              :               value_list<bool, (static_cast<void>(Bs), false)...>>::value>;
     546              : 
     547              : /*!
     548              :  * \ingroup UtilitiesGroup
     549              :  * \brief A non-short-circuiting logical OR between bools 'B""
     550              :  *
     551              :  * Useful when arbitrarily large parameter packs need to be evaluated, since
     552              :  * std::conjunction and std::disjunction use recursion
     553              :  */
     554              : template <bool... Bs>
     555            1 : constexpr bool flat_any_v = flat_any<Bs...>::value;
     556              : }  // namespace tmpl2
     557              : 
     558              : /*!
     559              :  * \ingroup UtilitiesGroup
     560              :  * \brief Allows zero-cost unordered expansion of a parameter
     561              :  *
     562              :  * \details
     563              :  * Expands a parameter pack, typically useful for runtime evaluation via a
     564              :  * Callable such as a lambda, function, or function object. For example,
     565              :  * an unordered transform of a std::tuple can be implemented as:
     566              :  * \snippet Utilities/Test_TMPL.cpp expand_pack_example
     567              :  *
     568              :  * \see tuple_fold tuple_counted_fold tuple_transform std::tuple
     569              :  * EXPAND_PACK_LEFT_TO_RIGHT
     570              :  */
     571              : template <typename... Ts>
     572            1 : constexpr void expand_pack(Ts&&... /*unused*/) {}
     573              : 
     574              : /*!
     575              :  * \ingroup UtilitiesGroup
     576              :  * \brief Expand a parameter pack evaluating the terms from left to right.
     577              :  *
     578              :  * The parameter pack inside the argument to the macro must not be expanded
     579              :  * since the macro will do the expansion correctly for you. In the below example
     580              :  * a parameter pack of `std::integral_constant<size_t, I>` is passed to the
     581              :  * function. The closure `lambda` is used to sum up the values of all the `Ts`.
     582              :  * Note that the `Ts` passed to `EXPAND_PACK_LEFT_TO_RIGHT` is not expanded.
     583              :  *
     584              :  * \snippet Utilities/Test_TMPL.cpp expand_pack_left_to_right
     585              :  *
     586              :  * \see tuple_fold tuple_counted_fold tuple_transform std::tuple expand_pack
     587              :  */
     588            1 : #define EXPAND_PACK_LEFT_TO_RIGHT(...) \
     589              :   (void)std::initializer_list<char> { ((void)(__VA_ARGS__), '0')... }
     590              : 
     591              : /*!
     592              :  * \ingroup UtilitiesGroup
     593              :  * \brief Returns the first argument of a parameter pack
     594              :  */
     595              : template <typename T, typename... Ts>
     596            1 : constexpr decltype(auto) get_first_argument(T&& t, Ts&&... /*rest*/) {
     597              :   return t;
     598              : }
     599              : 
     600              : namespace brigand {
     601              : namespace lazy {
     602              : /// Check if a typelist contains an item.
     603              : template <typename Sequence, typename Item>
     604            1 : struct list_contains;
     605              : 
     606              : /// \cond
     607              : template <template <typename...> typename L, typename... Items, typename Item>
     608              : struct list_contains<L<Items...>, Item>
     609              :     : bool_<(... or std::is_same_v<Items, Item>)> {};
     610              : /// \endcond
     611              : }  // namespace lazy
     612              : 
     613              : /// Check if a typelist contains an item.
     614              : /// @{
     615              : template <typename Sequence, typename Item>
     616            1 : using list_contains = typename lazy::list_contains<Sequence, Item>::type;
     617              : 
     618              : template <typename Sequence, typename Item>
     619            1 : constexpr bool list_contains_v = lazy::list_contains<Sequence, Item>::value;
     620              : /// @}
     621              : 
     622              : /// Obtain the elements of `Sequence1` that are not in `Sequence2`.
     623              : template <typename Sequence1, typename Sequence2>
     624            1 : using list_difference =
     625              :     fold<Sequence2, Sequence1, lazy::remove<_state, _element>>;
     626              : 
     627              : template <typename List>
     628            0 : using remove_duplicates = fold<List, clear<List>,
     629              :                                if_<lazy::list_contains<_state, _element>,
     630              :                                    _state, bind<push_back, _state, _element>>>;
     631              : 
     632              : namespace detail {
     633              : template <typename List>
     634              : struct as_pack_impl;
     635              : 
     636              : template <template <typename...> typename L, typename... Args>
     637              : struct as_pack_impl<L<Args...>> {
     638              :   template <typename F>
     639              :   static constexpr decltype(auto) apply(F&& f) {
     640              :     return std::forward<F>(f)(type_<Args>{}...);
     641              :   }
     642              : };
     643              : }  // namespace detail
     644              : 
     645              : /// Call a functor with the types from a list.
     646              : ///
     647              : /// Given a typelist `List = tmpl::list<A, B, ...>` (not necessarily
     648              : /// with head `tmpl::list`), calls \p f as `f(tmpl::type_<A>{},
     649              : /// tmpl::type_<B>{}, ...)` and returns the result.
     650              : ///
     651              : /// This is useful for converting a typelist into a parameter pack.
     652              : ///
     653              : /// \snippet Utilities/Test_TMPL.cpp as_pack
     654              : template <typename List, typename F>
     655            1 : constexpr decltype(auto) as_pack(F&& f) {
     656              :   return detail::as_pack_impl<List>::apply(std::forward<F>(f));
     657              : }
     658              : 
     659              : namespace detail {
     660              : template <typename Sequence>
     661              : struct make_std_variant_over_impl;
     662              : 
     663              : template <template <typename...> class Sequence, typename... Ts>
     664              : struct make_std_variant_over_impl<Sequence<Ts...>> {
     665              :   static_assert(((not std::is_same_v<std::decay_t<std::remove_pointer_t<Ts>>,
     666              :                                      void>)&&...),
     667              :                 "Cannot create a std::variant with a 'void' type.");
     668              :   using type = std::variant<Ts...>;
     669              : };
     670              : }  // namespace detail
     671              : 
     672              : /*!
     673              :  * \ingroup UtilitiesGroup
     674              :  * \brief Create a std::variant with all all the types inside the typelist
     675              :  * Sequence
     676              :  *
     677              :  * \metareturns std::variant of all types inside `Sequence`
     678              :  */
     679              : template <typename Sequence>
     680            1 : using make_std_variant_over = typename detail::make_std_variant_over_impl<
     681              :     tmpl::remove_duplicates<Sequence>>::type;
     682              : }  // namespace brigand
        

Generated by: LCOV version 2.0-1