ttg 1.0.0-alpha
Template Task Graph (TTG): flowgraph-based programming model for high-performance distributed-memory algorithms
Loading...
Searching...
No Matches
meta.h
Go to the documentation of this file.
1#ifndef TTG_UTIL_META_H
2#define TTG_UTIL_META_H
3
4#include <functional>
5#include <type_traits>
6
7#include "ttg/util/span.h"
8#include "ttg/util/typelist.h"
9
10namespace ttg {
11
12 class Void;
13
14 namespace meta {
15
16#if __cplusplus >= 201703L
17 using std::void_t;
18#else
19 template <class...>
20 using void_t = void;
21#endif
22
23 template <typename T>
24 using remove_cvr_t = std::remove_cv_t<std::remove_reference_t<T>>;
25
27 // (meta)tuple/typelist/typepack manipulations
29
30 // tuple<Ts...> -> tuple<std::remove_reference_t<Ts>...>
31 template <typename T, typename Enabler = void>
33
34 template <typename... Ts>
35 struct nonref_tuple<std::tuple<Ts...>> {
36 using type = std::tuple<typename std::remove_reference<Ts>::type...>;
37 };
38
39 template <typename Tuple>
41
42 template <typename... TupleTs>
44
45 template <typename... Ts>
46 struct tuple_concat<std::tuple<Ts...>> {
47 using type = std::tuple<Ts...>;
48 };
49
50 template <typename... Ts, typename... Us, typename... R>
51 struct tuple_concat<std::tuple<Ts...>, std::tuple<Us...>, R...> {
52 using type = typename tuple_concat<
53 decltype(std::tuple_cat(std::declval<std::tuple<Ts...>>(), std::declval<std::tuple<Us...>>())), R...>::type;
54 };
55
56 template <typename... TupleTs>
57 using tuple_concat_t = typename tuple_concat<TupleTs...>::type;
58
59 // filtered_tuple<tuple,p>::type returns tuple with types for which the predicate evaluates to true
60 template <typename Tuple, template <typename> typename Predicate>
62
63 namespace detail {
64 template <bool>
65 struct keep_or_drop {
66 template <typename E>
67 using type = std::tuple<E>;
68 };
69
70 template <>
72 template <typename E>
73 using type = std::tuple<>;
74 };
75 } // namespace detail
76
77 template <template <typename> typename Pred, typename... Es>
78 struct filtered_tuple<std::tuple<Es...>, Pred> {
79 using type = decltype(std::tuple_cat(
80 std::declval<typename detail::keep_or_drop<Pred<Es>::value>::template type<Es>>()...));
81 };
82
83 template <typename Tuple, template <typename> typename Pred>
85
86 // clang-format off
91 // clang-format on
92 template <template <typename> typename Predicate, bool Default, typename... Ts>
93 struct probe_last;
94
95 template <template <typename> typename Predicate, bool Default>
96 struct probe_last<Predicate, Default> : public std::bool_constant<Default> {};
97
98 template <template <typename> typename Predicate, bool Default, typename T>
99 struct probe_last<Predicate, Default, T> : public std::bool_constant<Predicate<T>::value> {};
100
101 template <template <typename> typename Predicate, bool Default, typename T1, typename... Ts>
102 struct probe_last<Predicate, Default, T1, Ts...> : public probe_last<Predicate, Default, Ts...> {};
103
104 template <template <typename> typename Predicate, bool Default, typename... Ts>
105 struct probe_last<Predicate, Default, std::tuple<Ts...>> : public probe_last<Predicate, Default, Ts...> {};
106
107 template <template <typename> typename Predicate, bool Default, typename... Ts>
108 struct probe_last<Predicate, Default, ttg::typelist<Ts...>> : public probe_last<Predicate, Default, Ts...> {};
109
110 // clang-format off
115 // clang-format on
116 template <template <typename> typename Predicate, bool Default, typename... Ts>
117 constexpr bool probe_last_v = probe_last<Predicate, Default, Ts...>::value;
118
119 // clang-format off
124 // clang-format on
125 template <template <typename> typename Predicate, bool Default, typename... Ts>
127
128 template <template <typename> typename Predicate, bool Default>
129 struct probe_first<Predicate, Default> : public std::bool_constant<Default> {};
130
131 template <template <typename> typename Predicate, bool Default, typename T1, typename... Ts>
132 struct probe_first<Predicate, Default, T1, Ts...> : public std::bool_constant<Predicate<T1>::value> {};
133
134 template <template <typename> typename Predicate, bool Default, typename... Ts>
135 struct probe_first<Predicate, Default, std::tuple<Ts...>> : public probe_first<Predicate, Default, Ts...> {};
136
137 template <template <typename> typename Predicate, bool Default, typename... Ts>
138 struct probe_first<Predicate, Default, ttg::typelist<Ts...>> : public probe_first<Predicate, Default, Ts...> {};
139
140 // clang-format off
145 // clang-format on
146 template <template <typename> typename Predicate, bool Default, typename... Ts>
147 constexpr bool probe_first_v = probe_first<Predicate, Default, Ts...>::value;
148
149 // clang-format off
153 // clang-format on
154 template <template <typename> typename Predicate, typename... Ts>
155 struct probe_any : std::bool_constant<(Predicate<Ts>::value || ...)> {};
156
157 template <template <typename> typename Predicate, typename... Ts>
158 struct probe_any<Predicate, std::tuple<Ts...>> : public probe_any<Predicate, Ts...> {};
159
160 template <template <typename> typename Predicate, typename... Ts>
161 struct probe_any<Predicate, ttg::typelist<Ts...>> : public probe_any<Predicate, Ts...> {};
162
163 // clang-format off
167 // clang-format on
168 template <template <typename> typename Predicate, typename... Ts>
169 constexpr bool probe_any_v = probe_any<Predicate, Ts...>::value;
170
171 // clang-format off
175 // clang-format on
176 template <template <typename> typename Predicate, typename... Ts>
177 struct probe_all : std::bool_constant<(Predicate<Ts>::value && ...)> {};
178
179 template <template <typename> typename Predicate, typename... Ts>
180 struct probe_all<Predicate, std::tuple<Ts...>> : public probe_all<Predicate, Ts...> {};
181
182 template <template <typename> typename Predicate, typename... Ts>
183 struct probe_all<Predicate, ttg::typelist<Ts...>> : public probe_all<Predicate, Ts...> {};
184
185 // clang-format off
189 // clang-format on
190 template <template <typename> typename Predicate, typename... Ts>
191 constexpr bool probe_all_v = probe_all<Predicate, Ts...>::value;
192
194 // is_Void_v
195 // is_void_v = Void or void
196 // is_none_void_v
197 // is_any_void_v
198 // is_last_void_v
199 // void_to_Void_t
200 // is_any_nonconst_lvalue_reference_v
202 template <typename T>
203 constexpr bool is_Void_v = std::is_same_v<std::decay_t<T>, Void>;
204
205 template <typename T>
206 constexpr bool is_void_v = is_Void_v<T> || std::is_void_v<T>;
207
208 template <typename T>
209 struct is_void : std::bool_constant<is_void_v<T>> {};
210
211 template <typename T>
212 constexpr bool is_nonvoid_v = !is_void_v<T>;
213
214 template <typename T>
215 struct is_nonvoid : std::bool_constant<is_nonvoid_v<T>> {};
216
217 template <typename... Ts>
218 constexpr bool is_all_void_v = (is_void_v<Ts> && ...);
219
220 template <typename... Ts>
221 constexpr bool is_all_void_v<ttg::typelist<Ts...>> = is_all_void_v<Ts...>;
222
223 template <typename... Ts>
224 constexpr bool is_all_Void_v = (is_Void_v<Ts> && ...);
225
226 template <typename... Ts>
227 constexpr bool is_all_Void_v<ttg::typelist<Ts...>> = is_all_Void_v<Ts...>;
228
229 template <typename... Ts>
230 constexpr bool is_any_void_v = (is_void_v<Ts> || ...);
231
232 template <typename... Ts>
233 constexpr bool is_any_void_v<ttg::typelist<Ts...>> = is_all_void_v<Ts...>;
234
235 template <typename... Ts>
236 constexpr bool is_any_Void_v = (is_Void_v<Ts> || ...);
237
238 template <typename... Ts>
239 constexpr bool is_any_Void_v<ttg::typelist<Ts...>> = is_any_Void_v<Ts...>;
240
241 template <typename... Ts>
242 constexpr bool is_none_void_v = !is_any_void_v<Ts...>;
243
244 template <typename... Ts>
245 constexpr bool is_none_void_v<ttg::typelist<Ts...>> = is_none_void_v<Ts...>;
246
247 template <typename... Ts>
248 constexpr bool is_none_Void_v = !is_any_Void_v<Ts...>;
249
250 template <typename... Ts>
251 constexpr bool is_none_Void_v<ttg::typelist<Ts...>> = is_none_Void_v<Ts...>;
252
253 template <typename... Ts>
254 struct is_last_void : probe_last<is_void, false, Ts...> {};
255
256 template <typename... Ts>
257 constexpr bool is_last_void_v = is_last_void<Ts...>::value;
258
259 template <typename T>
261 using type = T;
262 };
263 template <>
265 using type = Void;
266 };
267 template <typename T>
269
270 template <typename T>
272 std::is_lvalue_reference_v<T> &&std::is_const_v<std::remove_reference_t<T>>;
273
274 template <typename T>
275 struct is_const_lvalue_reference : std::bool_constant<is_const_lvalue_reference_v<T>> {};
276
277 template <typename T>
279 std::is_lvalue_reference_v<T> && !std::is_const_v<std::remove_reference_t<T>>;
280
281 template <typename T>
282 struct is_nonconst_lvalue_reference : std::bool_constant<is_nonconst_lvalue_reference_v<T>> {};
283
284 template <typename... Ts>
286
287 template <typename... Ts>
289
290 template <typename... Ts>
292
293
295 // device type traits
297
298 template<typename T>
299 struct is_ptr : std::false_type
300 { };
301
302 template<typename T>
303 constexpr bool is_ptr_v = is_ptr<T>::value;
304
305 /* specialized by the implementation */
306 template<typename T>
307 struct is_buffer : std::false_type
308 { };
309
310 template<typename T>
312
313 template<typename T>
314 struct is_devicescratch : std::false_type
315 { };
316
317 template<typename T>
319
320 template<typename T>
321 struct is_const : std::is_const<T>
322 { };
323
324 template<typename T>
326
328 // typelist metafunctions
330
332 template <typename Typelist, std::size_t N, typename Enabler = void>
334
335 template <typename... Ts>
336 struct drop_first_n<std::tuple<Ts...>, std::size_t(0)> {
337 using type = std::tuple<Ts...>;
338 };
339
340 template <typename... Ts>
341 struct drop_first_n<typelist<Ts...>, std::size_t(0)> {
342 using type = typelist<Ts...>;
343 };
344
345 template <typename T, typename... Ts, std::size_t N>
346 struct drop_first_n<std::tuple<T, Ts...>, N, std::enable_if_t<N != 0>> {
347 using type = typename drop_first_n<std::tuple<Ts...>, N - 1>::type;
348 };
349
350 template <typename T, typename... Ts, std::size_t N>
351 struct drop_first_n<typelist<T, Ts...>, N, std::enable_if_t<N != 0>> {
352 using type = typename drop_first_n<typelist<Ts...>, N - 1>::type;
353 };
354
356 template <typename Typelist, std::size_t N>
358
359 template <typename ResultTuple, typename InputTuple, std::size_t N, typename Enabler = void>
361
362 template <typename... Ts, typename... Us>
363 struct take_first_n_helper<std::tuple<Ts...>, std::tuple<Us...>, std::size_t(0)> {
364 using type = std::tuple<Ts...>;
365 };
366 template <typename... Ts, typename... Us>
368 using type = typelist<Ts...>;
369 };
370
371 template <typename... Ts, typename U, typename... Us, std::size_t N>
372 struct take_first_n_helper<std::tuple<Ts...>, std::tuple<U, Us...>, N, std::enable_if_t<N != 0>> {
373 using type = typename take_first_n_helper<std::tuple<Ts..., U>, std::tuple<Us...>, N - 1>::type;
374 };
375 template <typename... Ts, typename U, typename... Us, std::size_t N>
376 struct take_first_n_helper<typelist<Ts...>, typelist<U, Us...>, N, std::enable_if_t<N != 0>> {
377 using type = typename take_first_n_helper<typelist<Ts..., U>, typelist<Us...>, N - 1>::type;
378 };
379
380 template <typename... Ts, std::size_t N>
381 struct take_first_n<std::tuple<Ts...>, N> {
382 using type = typename take_first_n_helper<std::tuple<>, std::tuple<Ts...>, N>::type;
383 };
384
385 template <typename... Ts, std::size_t N>
386 struct take_first_n<typelist<Ts...>, N> {
387 using type = typename take_first_n_helper<typelist<>, typelist<Ts...>, N>::type;
388 };
389
391 template <typename Typelist, std::size_t N, typename Enabler = void>
393
394 template <typename... Ts, std::size_t N>
395 struct drop_last_n<std::tuple<Ts...>, N, std::enable_if_t<N <= sizeof...(Ts)>> {
396 using type = typename take_first_n<std::tuple<Ts...>, (sizeof...(Ts) - N)>::type;
397 };
398 template <typename... Ts, std::size_t N>
399 struct drop_last_n<typelist<Ts...>, N, std::enable_if_t<N <= sizeof...(Ts)>> {
400 using type = typename take_first_n<typelist<Ts...>, (sizeof...(Ts) - N)>::type;
401 };
402
403 template <typename... Ts, std::size_t N>
404 struct drop_last_n<std::tuple<Ts...>, N, std::enable_if_t<!(N <= sizeof...(Ts))>> {
405 using type = std::tuple<>;
406 };
407 template <typename... Ts, std::size_t N>
408 struct drop_last_n<typelist<Ts...>, N, std::enable_if_t<!(N <= sizeof...(Ts))>> {
409 using type = typelist<>;
410 };
411
413 template <typename T, typename Enabler = void>
414 struct decayed_typelist;
415
416 template <typename... Ts>
417 struct decayed_typelist<std::tuple<Ts...>> {
418 using type = std::tuple<std::decay_t<Ts>...>;
419 };
420 template <typename... Ts>
421 struct decayed_typelist<typelist<Ts...>> {
422 using type = typelist<std::decay_t<Ts>...>;
423 };
424
425 template <typename Tuple>
426 using decayed_typelist_t = typename decayed_typelist<Tuple>::type;
427
429 template <typename T, template <typename...> typename Pred>
430 struct filter;
431
432 template <typename FilteredTypelist, template <typename...> typename Pred, typename... ToBeFilteredTs>
433 struct filter_impl;
434
435 template <typename... FilteredTs, template <typename...> typename Pred>
436 struct filter_impl<typelist<FilteredTs...>, Pred> {
437 using type = typelist<FilteredTs...>;
438 };
439 template <typename... FilteredTs, template <typename...> typename Pred>
440 struct filter_impl<std::tuple<FilteredTs...>, Pred> {
441 using type = std::tuple<FilteredTs...>;
442 };
443
444 template <typename... FilteredTs, template <typename...> typename Pred, typename U, typename... RestOfUs>
445 struct filter_impl<typelist<FilteredTs...>, Pred, U, RestOfUs...>
446 : std::conditional_t<Pred<U>::value, filter_impl<typelist<FilteredTs..., U>, Pred, RestOfUs...>,
447 filter_impl<typelist<FilteredTs...>, Pred, RestOfUs...>> {};
448 template <typename... FilteredTs, template <typename...> typename Pred, typename U, typename... RestOfUs>
449 struct filter_impl<std::tuple<FilteredTs...>, Pred, U, RestOfUs...>
450 : std::conditional_t<Pred<U>::value, filter_impl<std::tuple<FilteredTs..., U>, Pred, RestOfUs...>,
451 filter_impl<std::tuple<FilteredTs...>, Pred, RestOfUs...>> {};
452
453 template <typename... Ts, template <typename...> typename Pred>
454 struct filter<typelist<Ts...>, Pred> : filter_impl<typelist<>, Pred, Ts...> {};
455 template <typename... Ts, template <typename...> typename Pred>
456 struct filter<std::tuple<Ts...>, Pred> : filter_impl<std::tuple<>, Pred, Ts...> {};
457
458 template <typename T, template <typename...> typename Pred>
459 using filter_t = typename filter<T, Pred>::type;
460
461 template <typename T>
463
464 template <typename T>
465 using drop_void_t = typename drop_void<T>::type;
466
467 template <typename T, typename S, typename U>
469
470 /* non-void S, replace with U */
471 template <typename... Ts, typename S, typename... Ss, typename U, typename... Us>
472 struct replace_nonvoid_helper<ttg::typelist<Ts...>, ttg::typelist<S, Ss...>, ttg::typelist<U, Us...>> {
473 using type =
475 };
476
477 /* void S, keep */
478 template <typename... Ts, typename... Ss, typename U, typename... Us>
479 struct replace_nonvoid_helper<ttg::typelist<Ts...>, ttg::typelist<void, Ss...>, ttg::typelist<U, Us...>> {
480 using type = typename replace_nonvoid_helper<ttg::typelist<Ts..., void>, ttg::typelist<Ss...>,
481 ttg::typelist<U, Us...>>::type;
482 };
483
484 /* empty S, done */
485 template <typename... Ts, typename... Us>
487 using type = ttg::typelist<Ts...>;
488 };
489
490 /* empty U, done */
491 template <typename... Ts, typename... Ss>
493 using type = ttg::typelist<Ts..., Ss...>;
494 };
495
496 /* empty S and U, done */
497 template <typename... Ts>
499 using type = ttg::typelist<Ts...>;
500 };
501
502 /* Replace the first min(sizeof...(T), sizeof...(U)) non-void types in T with types in U; U does not contain void */
503 template <typename T, typename U>
504 struct replace_nonvoid;
505
506 template <typename... T, typename... U>
507 struct replace_nonvoid<ttg::typelist<T...>, ttg::typelist<U...>> {
508 using type = typename replace_nonvoid_helper<ttg::typelist<>, ttg::typelist<T...>, ttg::typelist<U...>>::type;
509 };
510
511 template <typename... T, typename... U>
512 struct replace_nonvoid<std::tuple<T...>, std::tuple<U...>> {
513 using type =
515 };
516
517 template <typename T, typename U>
518 using replace_nonvoid_t = typename replace_nonvoid<T, U>::type;
519
521 // Tuple-element type conversions
523
524 template <typename T>
525 struct void_to_Void_tuple;
526
527 template <typename... Ts>
528 struct void_to_Void_tuple<std::tuple<Ts...>> {
529 using type = std::tuple<void_to_Void_t<Ts>...>;
530 };
531
532 template <typename tupleT>
534
535 template <typename T>
537
538 template <typename... Ts>
539 struct add_lvalue_reference_tuple<std::tuple<Ts...>> {
540 using type = std::tuple<std::add_lvalue_reference_t<Ts>...>;
541 };
542
543 template <typename tupleT>
544 using add_lvalue_reference_tuple_t = typename add_lvalue_reference_tuple<tupleT>::type;
545
546 template <typename T>
548
549 template <typename... Ts>
550 struct add_glvalue_reference_tuple<std::tuple<Ts...>> {
551 using type = std::tuple<std::conditional_t<std::is_const_v<Ts>, std::add_lvalue_reference_t<Ts>,
552 std::add_rvalue_reference_t<std::remove_const_t<Ts>>>...>;
553 };
554
555 template <typename tupleT>
556 using add_glvalue_reference_tuple_t = typename add_glvalue_reference_tuple<tupleT>::type;
557
558 template <typename T, typename... Ts>
559 struct none_has_reference {
560 static constexpr bool value = !std::is_reference_v<T> && none_has_reference<Ts...>::value;
561 };
562
563 template <typename T>
564 struct none_has_reference<T> {
565 static constexpr bool value = !std::is_reference_v<T>;
566 };
567
568 template <typename... T>
569 struct none_has_reference<ttg::typelist<T...>> : none_has_reference<T...> {};
570
571 template <>
572 struct none_has_reference<ttg::typelist<>> : std::true_type {};
573
574 template <typename... T>
575 constexpr bool none_has_reference_v = none_has_reference<T...>::value;
576
577 template <typename T>
578 struct is_tuple : std::integral_constant<bool, false> {};
579
580 template <typename... Ts>
581 struct is_tuple<std::tuple<Ts...>> : std::integral_constant<bool, true> {};
582
583 template <typename T>
584 constexpr bool is_tuple_v = is_tuple<T>::value;
585
586 template <typename>
587 struct is_span : std::false_type {};
588
589 template <typename T, std::size_t S>
590 struct is_span<ttg::span<T, S>> : std::true_type {};
591
592 template <typename T>
593 constexpr bool is_span_v = is_span<T>::value;
594
595 template <template <class> class Pred, typename TupleT, std::size_t I, std::size_t... Is>
597
598 template <template <class> class Pred, typename T, typename... Ts, std::size_t I, std::size_t... Is>
599 struct predicate_index_seq_helper<Pred, std::tuple<T, Ts...>, I, Is...> {
600 using seq = std::conditional_t<Pred<T>::value,
601 typename predicate_index_seq_helper<Pred, std::tuple<Ts...>, I + 1, Is..., I>::seq,
602 typename predicate_index_seq_helper<Pred, std::tuple<Ts...>, I + 1, Is...>::seq>;
603 };
604
605 template <template <class> class Pred, std::size_t I, std::size_t... Is>
606 struct predicate_index_seq_helper<Pred, std::tuple<>, I, Is...> {
607 using seq = std::index_sequence<Is...>;
608 };
609
610 template <typename T>
611 struct is_none_void_pred : std::integral_constant<bool, is_none_void_v<T>> {};
612
616 template <typename TupleT>
617 using nonvoid_index_seq = typename predicate_index_seq_helper<is_none_void_pred, TupleT, 0>::seq;
618
619 template <typename T>
620 struct is_void_pred : std::integral_constant<bool, is_void_v<T>> {};
621
625 template <typename TupleT>
626 using void_index_seq = typename predicate_index_seq_helper<is_void_pred, TupleT, 0>::seq;
627
629 // is_empty_tuple
631
632 // true if tuple is empty or contains only Void types, e.g. is_empty_tuple<std::tuple<>> or
633 // is_empty_tuple<std::tuple<Void>> evaluate to true
634 template <typename T, typename Enabler = void>
635 struct is_empty_tuple : std::false_type {};
636
637 template <typename... Ts>
638 struct is_empty_tuple<std::tuple<Ts...>, std::enable_if_t<(is_Void_v<Ts> && ...)>> : std::true_type {};
639
640 template <typename Tuple>
641 inline constexpr bool is_empty_tuple_v = is_empty_tuple<Tuple>::value;
642
643 static_assert(!is_empty_tuple_v<std::tuple<int>>, "ouch");
644 static_assert(is_empty_tuple_v<std::tuple<>>, "ouch");
645 static_assert(is_empty_tuple_v<std::tuple<Void>>, "ouch");
646 static_assert(is_empty_tuple_v<std::tuple<Void, Void, Void>>, "ouch");
647
649 // nonesuch struct from Library Fundamentals V2, source from https://en.cppreference.com/w/cpp/experimental/nonesuch
651
652 struct nonesuch {
653 ~nonesuch() = delete;
654 nonesuch(nonesuch const &) = delete;
655 void operator=(nonesuch const &) = delete;
656 };
657
659 // is_detected family from Library Fundamentals V2, source from
660 // https://en.cppreference.com/w/cpp/experimental/is_detected
662
663 namespace detail {
664
665 template <class Default, class Enabler, template <class...> class TT, class... Args>
666 struct detector {
667 using value_t = std::false_type;
668 using type = Default;
669 };
670
671 template <class Default, template <class...> class TT, class... Args>
672 struct detector<Default, void_t<TT<Args...>>, TT, Args...> {
673 using value_t = std::true_type;
674 using type = TT<Args...>;
675 };
676
677 } // namespace detail
678
679 template <template <class...> class TT, class... Args>
680 using is_detected = typename detail::detector<nonesuch, void, TT, Args...>::value_t;
681
682 template <template <class...> class TT, class... Args>
683 using detected_t = typename detail::detector<nonesuch, void, TT, Args...>::type;
684
685 template <class Default, template <class...> class TT, class... Args>
686 using detected_or = detail::detector<Default, void, TT, Args...>;
687
688 template <template <class...> class TT, class... Args>
689 constexpr bool is_detected_v = is_detected<TT, Args...>::value;
690
691 template <class Default, template <class...> class TT, class... Args>
692 using detected_or_t = typename detected_or<Default, TT, Args...>::type;
693
694 template <class Expected, template <class...> class TT, class... Args>
695 using is_detected_exact = std::is_same<Expected, detected_t<TT, Args...>>;
696
697 template <class Expected, template <class...> class TT, class... Args>
698 constexpr bool is_detected_exact_v = is_detected_exact<Expected, TT, Args...>::value;
699
700 template <class To, template <class...> class TT, class... Args>
701 using is_detected_convertible = std::is_convertible<detected_t<TT, Args...>, To>;
702
703 template <class To, template <class...> class TT, class... Args>
704 constexpr bool is_detected_convertible_v = is_detected_convertible<To, TT, Args...>::value;
705
707 // type_printer useful to print types in metaprograms
709
710 template <typename T>
711 struct type_printer;
712
714 // has_std_hash_specialization_v<T> evaluates to true if std::hash<T> is defined
716 template <typename T, typename Enabler = void>
717 struct has_std_hash_specialization : std::false_type {};
718 template <typename T>
720 T, ttg::meta::void_t<decltype(std::declval<std::hash<T>>()(std::declval<const T &>()))>> : std::true_type {};
721 template <typename T>
722 constexpr bool has_std_hash_specialization_v = has_std_hash_specialization<T>::value;
723
724 namespace detail {
725
727 // send_callback_t<key,value> = std::function<void(const key&, const value&>, protected against void key or value
729 template <typename Key, typename Value, typename Enabler = void>
730 struct send_callback;
731 template <typename Key, typename Value>
732 struct send_callback<Key, Value, std::enable_if_t<!is_void_v<Key> && !is_void_v<Value>>> {
733 using type = std::function<void(const Key &, const Value &)>;
734 };
735 template <typename Key, typename Value>
736 struct send_callback<Key, Value, std::enable_if_t<!is_void_v<Key> && is_void_v<Value>>> {
737 using type = std::function<void(const Key &)>;
738 };
739 template <typename Key, typename Value>
740 struct send_callback<Key, Value, std::enable_if_t<is_void_v<Key> && !is_void_v<Value>>> {
741 using type = std::function<void(const Value &)>;
742 };
743 template <typename Key, typename Value>
744 struct send_callback<Key, Value, std::enable_if_t<is_void_v<Key> && is_void_v<Value>>> {
745 using type = std::function<void()>;
746 };
747 template <typename Key, typename Value>
748 using send_callback_t = typename send_callback<Key, Value>::type;
749
751 // move_callback_t<key,value> = std::function<void(const key&, value&&>, protected against void key or value
753 template <typename Key, typename Value, typename Enabler = void>
754 struct move_callback;
755 template <typename Key, typename Value>
756 struct move_callback<Key, Value, std::enable_if_t<!is_void_v<Key> && !is_void_v<Value>>> {
757 using type = std::function<void(const Key &, Value &&)>;
758 };
759 template <typename Key, typename Value>
760 struct move_callback<Key, Value, std::enable_if_t<!is_void_v<Key> && is_void_v<Value>>> {
761 using type = std::function<void(const Key &)>;
762 };
763 template <typename Key, typename Value>
764 struct move_callback<Key, Value, std::enable_if_t<is_void_v<Key> && !is_void_v<Value>>> {
765 using type = std::function<void(Value &&)>;
766 };
767 template <typename Key, typename Value>
768 struct move_callback<Key, Value, std::enable_if_t<is_void_v<Key> && is_void_v<Value>>> {
769 using type = std::function<void()>;
770 };
771 template <typename Key, typename Value>
772 using move_callback_t = typename move_callback<Key, Value>::type;
773
775 // broadcast_callback_t<key,value> = std::function<void(const key&, value&&>, protected against void key or value
777 template <typename Key, typename Value, typename Enabler = void>
778 struct broadcast_callback;
779 template <typename Key, typename Value>
780 struct broadcast_callback<Key, Value, std::enable_if_t<!is_void_v<Key> && !is_void_v<Value>>> {
781 using type = std::function<void(const ttg::span<const Key> &, const Value &)>;
782 };
783 template <typename Key, typename Value>
784 struct broadcast_callback<Key, Value, std::enable_if_t<!is_void_v<Key> && is_void_v<Value>>> {
785 using type = std::function<void(const ttg::span<const Key> &)>;
786 };
787 template <typename Key, typename Value>
788 struct broadcast_callback<Key, Value, std::enable_if_t<is_void_v<Key> && !is_void_v<Value>>> {
789 using type = std::function<void(const Value &)>;
790 };
791 template <typename Key, typename Value>
792 struct broadcast_callback<Key, Value, std::enable_if_t<is_void_v<Key> && is_void_v<Value>>> {
793 using type = std::function<void()>;
794 };
795 template <typename Key, typename Value>
796 using broadcast_callback_t = typename broadcast_callback<Key, Value>::type;
797
798
799
801 // setsize_callback_t<key> = std::function<void(const keyT &, std::size_t)> protected against void key
803 template <typename Key, typename Enabler = void>
804 struct setsize_callback;
805 template <typename Key>
806 struct setsize_callback<Key, std::enable_if_t<!is_void_v<Key>>> {
807 using type = std::function<void(const Key &, std::size_t)>;
808 };
809 template <typename Key>
810 struct setsize_callback<Key, std::enable_if_t<is_void_v<Key>>> {
811 using type = std::function<void(std::size_t)>;
812 };
813 template <typename Key>
814 using setsize_callback_t = typename setsize_callback<Key>::type;
815
817 // finalize_callback_t<key> = std::function<void(const keyT &)> protected against void key
819 template <typename Key, typename Enabler = void>
820 struct finalize_callback;
821 template <typename Key>
822 struct finalize_callback<Key, std::enable_if_t<!is_void_v<Key>>> {
823 using type = std::function<void(const Key &)>;
824 };
825 template <typename Key>
826 struct finalize_callback<Key, std::enable_if_t<is_void_v<Key>>> {
827 using type = std::function<void()>;
828 };
829 template <typename Key>
830 using finalize_callback_t = typename finalize_callback<Key>::type;
831
833 // keymap_t<key,value> = std::function<int(const key&>, protected against void key
835 template <typename Key, typename Return, typename Enabler = void>
836 struct keymap;
837 template <typename Key, typename Return>
838 struct keymap<Key, Return, std::enable_if_t<!is_void_v<Key>>> {
839 using type = std::function<Return(const Key &)>;
840 };
841 template <typename Key, typename Return>
842 struct keymap<Key, Return, std::enable_if_t<is_void_v<Key>>> {
843 using type = std::function<Return()>;
844 };
845 template <typename Key, typename Return = int>
846 using keymap_t = typename keymap<Key, Return>::type;
847
849 // input_reducers_t<valueTs...> = std::tuple<
850 // std::function<std::decay_t<input_valueTs>(std::decay_t<input_valueTs> &&, std::decay_t<input_valueTs>
851 // &&)>...>
852 // protected against void valueTs
854 template <typename T, typename Enabler = void>
855 struct input_reducer_type;
856 template <typename T>
857 struct input_reducer_type<T, std::enable_if_t<!is_void_v<T>>> {
858 using type = std::function<void(std::decay_t<T> &, const std::decay_t<T> &)>;
859 };
860 template <typename T>
861 struct input_reducer_type<T, std::enable_if_t<is_void_v<T>>> {
862 using type = std::function<void()>;
863 };
864 template <typename... valueTs>
865 struct input_reducers {
866 using type = std::tuple<typename input_reducer_type<valueTs>::type...>;
867 };
868 template <typename... valueTs>
869 struct input_reducers<std::tuple<valueTs...>> {
870 using type = std::tuple<typename input_reducer_type<valueTs>::type...>;
871 };
872 template <typename... valueTs>
873 using input_reducers_t = typename input_reducers<valueTs...>::type;
874
876 // prepare_send_callback_t<Key, Value> = std::function<int(const ttg::span<Key> &, const Value &)> protected against void key
878 template <typename Key, typename Value, typename Enabler = void>
879 struct prepare_send_callback;
880 template <typename Key, typename Value>
881 struct prepare_send_callback<Key, Value, std::enable_if_t<!is_void_v<Key> && !is_void_v<Value>>> {
882 using type = std::function<void(const ttg::span<const Key> &, const Value &)>;
883 };
884 template <typename Key, typename Value>
885 struct prepare_send_callback<Key, Value, std::enable_if_t<!is_void_v<Key> && is_void_v<Value>>> {
886 using type = std::function<void(const ttg::span<const Key> &)>;
887 };
888 template <typename Key, typename Value>
889 struct prepare_send_callback<Key, Value, std::enable_if_t<is_void_v<Key> && !is_void_v<Value>>> {
890 using type = std::function<void(const Value &)>;
891 };
892 template <typename Key, typename Value>
893 struct prepare_send_callback<Key, Value, std::enable_if_t<is_void_v<Key> && is_void_v<Value>>> {
894 using type = std::function<void()>;
895 };
896 template <typename Key, typename Value>
897 using prepare_send_callback_t = typename prepare_send_callback<Key, Value>::type;
898
899 template<typename Key, typename Enabler = void>
900 struct constraint_callback;
901
902 template<typename Key>
903 struct constraint_callback<Key, std::enable_if_t<!is_void_v<Key>>> {
904 using type = std::function<bool(const Key&)>;
905 };
906
907 template<typename Key>
908 struct constraint_callback<Key, std::enable_if_t<is_void_v<Key>>> {
909 using type = std::function<bool()>;
910 };
911
912 template<typename Key>
913 using constraint_callback_t = typename constraint_callback<Key>::type;
914
915 } // namespace detail
916
918 // check whether a type is iterable
919 // Taken from https://en.cppreference.com/w/cpp/types/void_t
921 template <typename T, typename = void>
922 struct is_iterable : std::false_type {};
923
924 // this gets used only when we can call std::begin() and std::end() on that type
925 template <typename T>
926 struct is_iterable<T, std::void_t<decltype(std::begin(std::declval<T>())), decltype(std::end(std::declval<T>()))>>
927 : std::true_type {};
928
929 template <typename T>
930 constexpr bool is_iterable_v = is_iterable<T>::value;
931
933 // check whether a Callable is invocable with the arguments given as a typelist
935 template <typename Callable, typename Typelist>
936 constexpr bool is_invocable_typelist_v = false;
937 template <typename Callable, typename... Args>
938 constexpr bool is_invocable_typelist_v<Callable, ttg::typelist<Args...>> = std::is_invocable_v<Callable, Args...>;
939 template <typename ReturnType, typename Callable, typename Typelist>
940 constexpr bool is_invocable_typelist_r_v = false;
941 template <typename ReturnType, typename Callable, typename... Args>
943 std::is_invocable_r_v<ReturnType, Callable, Args...>;
944
946 // detects the return result of a Callable when invoked with the arguments given as a typelist
948 template <typename Callable, typename Typelist>
949 struct invoke_result_typelist {};
950 template <typename Callable, typename... Args>
951 struct invoke_result_typelist<Callable, ttg::typelist<Args...>> : std::invoke_result<Callable, Args...> {};
952 template <class F, class... ArgTypes>
953 using invoke_result_typelist_t = typename invoke_result_typelist<F, ArgTypes...>::type;
954
955 } // namespace meta
956} // namespace ttg
957
958#endif // TTG_UTIL_META_H
A complete version of void.
Definition void.h:11
STL namespace.
constexpr bool is_none_Void_v
Definition meta.h:248
typename void_to_Void< T >::type void_to_Void_t
Definition meta.h:268
constexpr bool is_Void_v
Definition meta.h:203
constexpr bool is_any_nonconst_lvalue_reference_v
Definition meta.h:285
constexpr bool probe_last_v
Definition meta.h:117
constexpr bool is_any_void_v
Definition meta.h:230
constexpr bool probe_any_v
Definition meta.h:169
constexpr bool probe_all_v
Definition meta.h:191
constexpr bool is_all_Void_v
Definition meta.h:224
void void_t
Definition meta.h:20
typename nonref_tuple< Tuple >::type nonref_tuple_t
Definition meta.h:40
constexpr bool is_any_Void_v
Definition meta.h:236
constexpr bool is_devicescratch_v
Definition meta.h:318
std::remove_cv_t< std::remove_reference_t< T > > remove_cvr_t
Definition meta.h:24
constexpr bool is_last_void_v
Definition meta.h:257
constexpr bool is_nonconst_lvalue_reference_v
Definition meta.h:278
constexpr bool is_const_lvalue_reference_v
Definition meta.h:271
constexpr bool probe_first_v
Definition meta.h:147
constexpr bool is_buffer_v
Definition meta.h:311
constexpr bool is_ptr_v
Definition meta.h:303
typename filtered_tuple< Tuple, Pred >::type filtered_tuple_t
Definition meta.h:84
constexpr bool is_nonvoid_v
Definition meta.h:212
typename tuple_concat< TupleTs... >::type tuple_concat_t
Definition meta.h:57
constexpr bool is_const_v
Definition meta.h:325
constexpr bool is_none_void_v
Definition meta.h:242
typename typelist_to_tuple< T >::type typelist_to_tuple_t
Definition typelist.h:52
constexpr bool is_all_void_v
Definition meta.h:218
constexpr bool is_void_v
Definition meta.h:206
constexpr auto get(typelist< T, RestOfTs... >)
Definition typelist.h:101
top-level TTG namespace contains runtime-neutral functionality
Definition keymap.h:8
meta::typelist< Ts... > typelist
Definition typelist.h:81
std::tuple< E > type
Definition meta.h:67
typename drop_first_n< std::tuple< Ts... >, N - 1 >::type type
Definition meta.h:347
typename drop_first_n< typelist< Ts... >, N - 1 >::type type
Definition meta.h:352
drops N elements from the front
Definition meta.h:333
drops N trailing elements from a typelist
Definition meta.h:392
decltype(std::tuple_cat(std::declval< typename detail::keep_or_drop< Pred< Es >::value >::template type< Es > >()...)) type
Definition meta.h:80
std::tuple< typename std::remove_reference< Ts >::type... > type
Definition meta.h:36
typename take_first_n_helper< std::tuple<>, std::tuple< Ts... >, N >::type type
Definition meta.h:382
typename take_first_n_helper< typelist<>, typelist< Ts... >, N >::type type
Definition meta.h:387
typename take_first_n_helper< std::tuple< Ts..., U >, std::tuple< Us... >, N - 1 >::type type
Definition meta.h:373
typename take_first_n_helper< typelist< Ts..., U >, typelist< Us... >, N - 1 >::type type
Definition meta.h:377
take first N elements of a type list
Definition meta.h:357
typename tuple_concat< decltype(std::tuple_cat(std::declval< std::tuple< Ts... > >(), std::declval< std::tuple< Us... > >())), R... >::type type
Definition meta.h:53
A container for types.
Definition typelist.h:24