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