TMPL.hpp
Go to the documentation of this file.
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 <initializer_list>
21 
22 #include "Utilities/Digraph.hpp"
24 
25 namespace brigand {
26 namespace detail {
27 template <bool b, typename O, typename L, std::size_t I, typename R,
28  typename U = void>
29 struct replace_at_impl;
30 
31 template <template <typename...> class S, typename... Os, typename... Ts,
32  typename R>
33 struct replace_at_impl<false, S<Os...>, S<Ts...>, 0, R> {
34  using type = S<Os..., Ts...>;
35 };
36 
37 template <template <typename...> class S, typename... Os, typename... Ts,
38  typename T, typename R>
39 struct replace_at_impl<false, S<Os...>, S<T, Ts...>, 1, R>
40  : replace_at_impl<false, S<Os..., R>, S<Ts...>, 0, R> {};
41 
42 template <template <typename...> class S, typename... Os, typename T,
43  typename... Ts, std::size_t I, typename R>
44 struct replace_at_impl<false, S<Os...>, S<T, Ts...>, I, R,
45  typename std::enable_if<(I > 1)>::type>
46  : replace_at_impl<false, S<Os..., T>, S<Ts...>, (I - 1), R> {};
47 
48 template <template <typename...> class S, typename... Os, typename T1,
49  typename T2, typename T3, typename T4, typename T5, typename T6,
50  typename T7, typename T8, typename T9, typename T10, typename T11,
51  typename T12, typename T13, typename T14, typename T15, typename T16,
52  typename... Ts, std::size_t I, typename R>
53 struct replace_at_impl<true, S<Os...>,
54  S<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
55  T14, T15, T16, Ts...>,
56  I, R>
57  : replace_at_impl<((I - 16) > 16), S<Os..., T1, T2, T3, T4, T5, T6, T7, T8,
58  T9, T10, T11, T12, T13, T14, T15, T16>,
59  S<Ts...>, (I - 16), R> {};
60 
61 template <typename L, typename I, typename R>
62 struct call_replace_at_impl
63  : replace_at_impl<(I::value > 15), brigand::clear<L>, L, I::value + 1, R> {
64 };
65 }
66 
67 namespace lazy {
68 template <typename L, typename I, typename R>
69 using replace_at = ::brigand::detail::call_replace_at_impl<L, I, R>;
70 }
71 template <typename L, typename I, typename R>
72 using replace_at = typename ::brigand::lazy::replace_at<L, I, R>::type;
73 } // namespace brigand
74 
75 namespace brigand {
76 namespace detail {
77 template <typename List, typename Ind1, typename Ind2>
78 struct swap_at_impl {
79  using type = ::brigand::replace_at<
80  ::brigand::replace_at<List, Ind1, ::brigand::at<List, Ind2>>, Ind2,
81  ::brigand::at<List, Ind1>>;
82 };
83 }
84 
85 template <typename List, typename Ind1, typename Ind2>
86 using swap_at =
87  typename ::brigand::detail::swap_at_impl<List, Ind1, Ind2>::type;
88 }
89 
90 namespace brigand {
91 template <typename V>
92 using abs = std::integral_constant<typename V::value_type,
93  (V::value < 0 ? -V::value : V::value)>;
94 
95 template <typename V>
96 using sign =
97  std::integral_constant<typename V::value_type, (V::value < 0 ? -1 : 1)>;
98 
99 template <int T>
100 using int_ = std::integral_constant<int, T>;
101 
102 template <typename V, typename N>
103 struct power
105  typename V::value_type,
106  V::value * power<V, std::integral_constant<typename N::value_type,
107  N::value - 1>>::value> {};
108 
109 template <typename V, typename T>
110 struct power<V, std::integral_constant<T, 0>>
111  : std::integral_constant<typename V::value_type, 1> {};
112 
113 template <typename T>
114 struct factorial : times<T, factorial<uint64_t<T::value - 1>>> {};
115 template <>
116 struct factorial<uint64_t<1>> : uint64_t<1> {};
117 }
118 
119 namespace brigand {
120 namespace detail {
121 template <typename List, std::size_t Size = size<List>::value>
122 struct permutations_impl {
123  template <typename T, typename List1>
124  struct helper {
125  using type = ::brigand::transform<
126  typename permutations_impl<::brigand::remove<List1, T>>::type,
127  ::brigand::lazy::push_front<_state, T>>;
128  };
129 
130  using type = ::brigand::fold<
131  List, list<>,
132  ::brigand::lazy::append<::brigand::_state, helper<::brigand::_element,
133  ::brigand::pin<List>>>>;
134 };
135 
136 template <typename List>
137 struct permutations_impl<List, 1> {
138  using type = list<List>;
139 };
140 }
141 
142 namespace lazy {
143 template <typename List>
144 using permutations = detail::permutations_impl<List>;
145 }
146 
147 template <typename List>
148 using permutations = typename lazy::permutations<List>::type;
149 }
150 
151 namespace brigand {
152 namespace detail {
153 template <typename List, std::size_t Size = ::brigand::size<List>::value>
154 struct generic_permutations_impl {
155  template <typename Lc, typename List1>
156  struct helper {
157  using type = ::brigand::transform<
158  typename generic_permutations_impl<::brigand::erase<List1, Lc>>::type,
159  ::brigand::lazy::push_front<::brigand::_state,
160  ::brigand::at<List1, Lc>>>;
161  };
162  using type = ::brigand::fold<
163  ::brigand::make_sequence<brigand::uint32_t<0>, Size>, ::brigand::list<>,
164  ::brigand::lazy::append<::brigand::_state, helper<::brigand::_element,
165  ::brigand::pin<List>>>>;
166 };
167 
168 template <typename List>
169 struct generic_permutations_impl<List, 1> {
170  using type = ::brigand::list<List>;
171 };
172 }
173 
174 namespace lazy {
175 template <typename List>
176 using generic_permutations = detail::generic_permutations_impl<List>;
177 }
178 
179 template <typename List>
180 using generic_permutations = typename lazy::generic_permutations<List>::type;
181 }
182 
183 namespace brigand {
184 namespace detail {
185 template <typename List, typename Number = uint32_t<1>>
186 struct combinations_impl_helper {
187  using split_list = split_at<List, Number>;
188  using type =
189  fold<back<split_list>, list<>,
190  lazy::append<
191  _state,
192  bind<list, bind<push_back, pin<front<split_list>>, _element>>>>;
193 };
194 
195 template <typename List, typename OutSize, typename = void>
196 struct combinations_impl {
197  using type =
198  append<list<>,
199  typename combinations_impl_helper<List, prev<OutSize>>::type,
200  typename combinations_impl<pop_front<List>, OutSize>::type>;
201 };
202 template <typename List, typename OutSize>
203 struct combinations_impl<
204  List, OutSize,
205  typename std::enable_if<OutSize::value == size<List>::value>::type> {
206  using type = typename combinations_impl_helper<List, prev<OutSize>>::type;
207 };
208 }
209 
210 namespace lazy {
211 template <typename List, typename OutSize = uint32_t<2>>
212 using combinations = detail::combinations_impl<List, OutSize>;
213 }
214 
215 template <typename List, typename OutSize = uint32_t<2>>
216 using combinations = typename lazy::combinations<List, OutSize>::type;
217 }
218 
219 namespace brigand {
220 namespace detail {
221 template <typename Seq, typename T>
222 struct equal_members_helper
223  : std::is_same<count_if<Seq, std::is_same<T, _1>>, size_t<1>> {};
224 }
225 
226 template <typename List1, typename List2>
227 using equal_members = and_<
228  fold<List1, bool_<true>,
229  and_<_state, detail::equal_members_helper<pin<List2>, _element>>>,
230  fold<List2, bool_<true>,
231  and_<_state, detail::equal_members_helper<pin<List1>, _element>>>>;
232 }
233 
234 namespace brigand {
235 namespace detail {
236 template <typename Functor, typename State, typename I, typename Sequence>
237 struct enumerated_fold_impl {
238  using type = State;
239 };
240 
241 template <typename Functor, typename State, typename I,
242  template <typename...> class Sequence, typename T0>
243 struct enumerated_fold_impl<Functor, State, I, Sequence<T0>> {
244  using type = brigand::apply<Functor, State, T0, I>;
245 };
246 
247 template <typename Functor, typename State, typename I,
248  template <typename...> class Sequence, typename T0, typename T1>
249 struct enumerated_fold_impl<Functor, State, I, Sequence<T0, T1>> {
250  using type = brigand::apply<Functor, brigand::apply<Functor, State, T0, I>,
251  T1, brigand::next<I>>;
252 };
253 
254 template <typename Functor, typename State, typename I,
255  template <typename...> class Sequence, typename T0, typename T1,
256  typename T2>
257 struct enumerated_fold_impl<Functor, State, I, Sequence<T0, T1, T2>> {
258  using type = brigand::apply<
259  Functor, brigand::apply<Functor, brigand::apply<Functor, State, T0, I>,
260  T1, brigand::next<I>>,
261  T2, brigand::plus<I, brigand::int32_t<2>>>;
262 };
263 
264 template <typename Functor, typename State, typename I,
265  template <typename...> class Sequence, typename T0, typename T1,
266  typename T2, typename T3>
267 struct enumerated_fold_impl<Functor, State, I, Sequence<T0, T1, T2, T3>> {
268  using type = brigand::apply<
269  Functor,
271  Functor,
272  brigand::apply<Functor, brigand::apply<Functor, State, T0, I>, T1,
273  brigand::next<I>>,
274  T2, brigand::plus<I, brigand::int32_t<2>>>,
275  T3, brigand::plus<I, brigand::int32_t<3>>>;
276 };
277 
278 template <typename Functor, typename State, typename I,
279  template <typename...> class Sequence, typename T0, typename T1,
280  typename T2, typename T3, typename T4>
281 struct enumerated_fold_impl<Functor, State, I, Sequence<T0, T1, T2, T3, T4>> {
282  using type = brigand::apply<
283  Functor,
285  Functor,
287  Functor,
288  brigand::apply<Functor, brigand::apply<Functor, State, T0, I>, T1,
289  brigand::next<I>>,
290  T2, brigand::plus<I, brigand::int32_t<2>>>,
291  T3, brigand::plus<I, brigand::int32_t<3>>>,
292  T4, brigand::plus<I, brigand::int32_t<4>>>;
293 };
294 
295 template <typename Functor, typename State, typename I,
296  template <typename...> class Sequence, typename T0, typename T1,
297  typename T2, typename T3, typename T4, typename T5>
298 struct enumerated_fold_impl<Functor, State, I,
299  Sequence<T0, T1, T2, T3, T4, T5>> {
300  using type = brigand::apply<
301  Functor,
303  Functor,
305  Functor,
307  Functor,
308  brigand::apply<Functor, brigand::apply<Functor, State, T0, I>,
309  T1, brigand::next<I>>,
310  T2, brigand::plus<I, brigand::int32_t<2>>>,
311  T3, brigand::plus<I, brigand::int32_t<3>>>,
312  T4, brigand::plus<I, brigand::int32_t<4>>>,
313  T5, brigand::plus<I, brigand::int32_t<5>>>;
314 };
315 
316 template <typename Functor, typename State, typename I,
317  template <typename...> class Sequence, typename T0, typename T1,
318  typename T2, typename T3, typename T4, typename T5, typename T6>
319 struct enumerated_fold_impl<Functor, State, I,
320  Sequence<T0, T1, T2, T3, T4, T5, T6>> {
321  using type = brigand::apply<
322  Functor,
324  Functor,
326  Functor,
328  Functor, brigand::apply<
329  Functor, brigand::apply<
330  Functor, brigand::apply<
331  Functor, State, T0, I>,
332  T1, brigand::next<I>>,
333  T2, brigand::plus<I, brigand::int32_t<2>>>,
334  T3, brigand::plus<I, brigand::int32_t<3>>>,
335  T4, brigand::plus<I, brigand::int32_t<4>>>,
336  T5, brigand::plus<I, brigand::int32_t<5>>>,
337  T6, brigand::plus<I, brigand::int32_t<6>>>;
338 };
339 
340 template <typename Functor, typename State, typename I,
341  template <typename...> class Sequence, typename T0, typename T1,
342  typename T2, typename T3, typename T4, typename T5, typename T6,
343  typename T7>
344 struct enumerated_fold_impl<Functor, State, I,
345  Sequence<T0, T1, T2, T3, T4, T5, T6, T7>> {
346  using type = brigand::apply<
347  Functor,
349  Functor,
351  Functor,
353  Functor,
355  Functor,
357  Functor,
358  brigand::apply<Functor,
359  brigand::apply<Functor, State, T0, I>,
360  T1, brigand::next<I>>,
361  T2, brigand::plus<I, brigand::int32_t<2>>>,
362  T3, brigand::plus<I, brigand::int32_t<3>>>,
363  T4, brigand::plus<I, brigand::int32_t<4>>>,
364  T5, brigand::plus<I, brigand::int32_t<5>>>,
365  T6, brigand::plus<I, brigand::int32_t<6>>>,
366  T7, brigand::plus<I, brigand::int32_t<7>>>;
367 };
368 
369 template <typename Functor, typename State, typename I,
370  template <typename...> class Sequence, typename T0, typename T1,
371  typename T2, typename T3, typename T4, typename T5, typename T6,
372  typename T7, typename... T>
373 struct enumerated_fold_impl<Functor, State, I,
374  Sequence<T0, T1, T2, T3, T4, T5, T6, T7, T...>>
375  : enumerated_fold_impl<
376  Functor,
377  brigand::apply<
378  Functor,
379  brigand::apply<
380  Functor,
381  brigand::apply<
382  Functor,
383  brigand::apply<
384  Functor,
385  brigand::apply<
386  Functor,
387  brigand::apply<
388  Functor,
389  brigand::apply<
390  Functor,
391  brigand::apply<Functor, State, T0, I>, T1,
392  brigand::next<I>>,
393  T2, brigand::plus<I, brigand::int32_t<2>>>,
394  T3, brigand::plus<I, brigand::int32_t<3>>>,
395  T4, brigand::plus<I, brigand::int32_t<4>>>,
396  T5, brigand::plus<I, brigand::int32_t<5>>>,
397  T6, brigand::plus<I, brigand::int32_t<6>>>,
398  T7, brigand::plus<I, brigand::int32_t<7>>>,
399  brigand::plus<I, brigand::int32_t<8>>, Sequence<T...>> {};
400 }
401 
402 namespace lazy {
403 template <typename Sequence, typename State, typename Functor,
404  typename I = brigand::int32_t<0>>
405 using enumerated_fold =
406  typename detail::enumerated_fold_impl<Functor, State, I, Sequence>;
407 }
408 
409 template <typename Sequence, typename State, typename Functor,
410  typename I = brigand::int32_t<0>>
411 using enumerated_fold =
412  typename lazy::enumerated_fold<Sequence, State, Functor, I>::type;
413 }
414 
415 namespace brigand {
416 namespace detail {
417 template <typename S, typename E>
418 struct remove_duplicates_helper {
419  using type = typename std::conditional<
420  std::is_same<index_of<S, E>, no_such_type_>::value, push_back<S, E>,
421  S>::type;
422 };
423 }
424 
425 template <typename List>
426 using remove_duplicates =
427  fold<List, list<>, detail::remove_duplicates_helper<_state, _element>>;
428 }
429 
430 namespace brigand {
431 template <bool>
432 struct conditional;
433 
434 template <>
435 struct conditional<true> {
436  template <typename T, typename F>
437  using type = T;
438 };
439 
440 template <>
441 struct conditional<false> {
442  template <typename T, typename F>
443  using type = F;
444 };
445 
446 template <bool B, typename T, typename F>
447 using conditional_t = typename conditional<B>::template type<T, F>;
448 }
449 
450 namespace brigand {
451 template <bool>
452 struct branch_if;
453 
454 template <>
455 struct branch_if<true> {
456  template <typename T, typename F>
457  using type = typename detail::apply<T>::type;
458 };
459 
460 template <>
461 struct branch_if<false> {
462  template <typename T, typename F>
463  using type = typename detail::apply<F>::type;
464 };
465 
466 template <bool B, typename T, typename F>
467 using branch_if_t = typename branch_if<B>::template type<T, F>;
468 }
469 
470 namespace tmpl = brigand;
471 
472 /*!
473  * \ingroup UtilitiesGroup
474  * \brief Metaprogramming things that are not planned to be submitted to Brigand
475  */
476 namespace tmpl2 {
477 /*!
478  * \ingroup UtilitiesGroup
479  * \brief A compile-time list of values of the same type
480  */
481 template <class T, T...>
482 struct value_list {};
483 
484 /*!
485  * \ingroup UtilitiesGroup
486  * \brief A non-short-circuiting logical AND between bools 'B""
487  *
488  * Useful when arbitrarily large parameter packs need to be evaluated, since
489  * cpp17::conjunction and cpp17::disjunction use recursion
490  */
491 template <bool... Bs>
492 using flat_all =
493  std::is_same<value_list<bool, Bs...>,
495 
496 /*!
497  * \ingroup UtilitiesGroup
498  * \brief A non-short-circuiting logical AND between bools 'B""
499  *
500  * Useful when arbitrarily large parameter packs need to be evaluated, since
501  * cpp17::conjunction and cpp17::disjunction use recursion
502  */
503 template <bool... Bs>
504 constexpr bool flat_all_v = flat_all<Bs...>::value;
505 
506 /*!
507  * \ingroup UtilitiesGroup
508  * \brief A non-short-circuiting logical OR between bools 'B""
509  *
510  * Useful when arbitrarily large parameter packs need to be evaluated, since
511  * cpp17::conjunction and cpp17::disjunction use recursion
512  */
513 template <bool... Bs>
515  bool,
516  not std::is_same<
517  value_list<bool, Bs...>,
518  value_list<bool, (static_cast<void>(Bs), false)...>>::value>;
519 
520 /*!
521  * \ingroup UtilitiesGroup
522  * \brief A non-short-circuiting logical OR between bools 'B""
523  *
524  * Useful when arbitrarily large parameter packs need to be evaluated, since
525  * cpp17::conjunction and cpp17::disjunction use recursion
526  */
527 template <bool... Bs>
528 constexpr bool flat_any_v = flat_any<Bs...>::value;
529 } // namespace tmpl2
530 
531 /*!
532  * \ingroup UtilitiesGroup
533  * \brief Allows zero-cost unordered expansion of a parameter
534  *
535  * \details
536  * Expands a parameter pack, typically useful for runtime evaluation via a
537  * Callable such as a lambda, function, or function object. For example,
538  * an unordered transform of a std::tuple can be implemented as:
539  * \snippet Utilities/Test_TMPL.cpp expand_pack_example
540  *
541  * \see tuple_fold tuple_counted_fold tuple_transform std::tuple
542  * EXPAND_PACK_LEFT_TO_RIGHT
543  */
544 template <typename... Ts>
545 constexpr void expand_pack(Ts&&...) noexcept {}
546 
547 /*!
548  * \ingroup UtilitiesGroup
549  * \brief Expand a parameter pack evaluating the terms from left to right.
550  *
551  * The parameter pack inside the argument to the macro must not be expanded
552  * since the macro will do the expansion correctly for you. In the below example
553  * a parameter pack of `std::integral_constant<size_t, I>` is passed to the
554  * function. The closure `lambda` is used to sum up the values of all the `Ts`.
555  * Note that the `Ts` passed to `EXPAND_PACK_LEFT_TO_RIGHT` is not expanded.
556  *
557  * \snippet Utilities/Test_TMPL.cpp expand_pack_left_to_right
558  *
559  * \see tuple_fold tuple_counted_fold tuple_transform std::tuple expand_pack
560  */
561 #define EXPAND_PACK_LEFT_TO_RIGHT(...) \
562  (void)std::initializer_list<char> { ((void)(__VA_ARGS__), '0')... }
563 
564 /*!
565  * \ingroup UtilitiesGroup
566  * \brief Returns the first argument of a parameter pack
567  */
568 template <typename T, typename... Ts>
569 constexpr decltype(auto) get_first_argument(T&& t, Ts&&... /*rest*/) noexcept {
570  return t;
571 }
572 
573 namespace brigand {
574 /// Check if a typelist contains an item.
575 template <typename Sequence, typename Item>
576 using list_contains =
577  tmpl::found<Sequence, std::is_same<tmpl::_1, tmpl::pin<Item>>>;
578 
579 template <typename Sequence, typename Item>
580 constexpr const bool list_contains_v = list_contains<Sequence, Item>::value;
581 
582 /// Obtain the elements of `Sequence1` that are not in `Sequence2`.
583 template <typename Sequence1, typename Sequence2>
584 using list_difference =
585  fold<Sequence2, Sequence1, lazy::remove<_state, _element>>;
586 } // namespace brigand
constexpr bool flat_any_v
A non-short-circuiting logical OR between bools &#39;B"".
Definition: TMPL.hpp:528
constexpr bool flat_all_v
A non-short-circuiting logical AND between bools &#39;B"".
Definition: TMPL.hpp:504
Definition: Digraph.hpp:11
constexpr std::array< std::decay_t< T >, Size > replace_at(const std::array< T, Size > &arr, T value)
Replace at compile time the Ith entry in the array with value
Definition: ConstantExpressions.hpp:383
decltype(auto) constexpr get_first_argument(T &&t, Ts &&...) noexcept
Returns the first argument of a parameter pack.
Definition: TMPL.hpp:569
constexpr auto apply(F &&f, const DataBox< BoxTags > &box, Args &&... args)
Apply the function f with argument Tags TagsList from DataBox box
Definition: DataBox.hpp:1595
Definition: Determinant.hpp:11
A compile-time list of values of the same type.
Definition: TMPL.hpp:482
Defines macro to always inline a function.
constexpr uint64_t factorial(const uint64_t n) noexcept
Compute the factorial of .
Definition: ConstantExpressions.hpp:86
Metaprogramming things that are not planned to be submitted to Brigand.
Definition: TMPL.hpp:476
constexpr void expand_pack(Ts &&...) noexcept
Allows zero-cost unordered expansion of a parameter.
Definition: TMPL.hpp:545