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