timemory 3.3.0
Modular C++ Toolkit for Performance Analysis and Logging. Profiling API and Tools for C, C++, CUDA, Fortran, and Python. The C++ template API is essentially a framework to creating tools: it is designed to provide a unifying interface for recording various performance measurements alongside data logging and interfaces to other tools.
apply.hpp
Go to the documentation of this file.
1// MIT License
2//
3// Copyright (c) 2020, The Regents of the University of California,
4// through Lawrence Berkeley National Laboratory (subject to receipt of any
5// required approvals from the U.S. Dept. of Energy). All rights reserved.
6//
7// Permission is hereby granted, free of charge, to any person obtaining a copy
8// of this software and associated documentation files (the "Software"), to
9// deal in the Software without restriction, including without limitation the
10// rights to use, copy, modify, merge, publish, distribute, sublicense, and
11// copies of the Software, and to permit persons to whom the Software is
12// furnished to do so, subject to the following conditions:
13//
14// The above copyright notice and this permission notice shall be included in
15// all copies or substantial portions of the Software.
16//
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23// IN THE SOFTWARE.
24
25#pragma once
26
28#include "timemory/mpl/math.hpp"
29#include "timemory/mpl/stl.hpp"
30
31#include <functional>
32#include <initializer_list>
33#include <iomanip>
34#include <sstream>
35#include <string>
36#include <tuple>
37#include <type_traits>
38
39//======================================================================================//
40
41namespace tim
42{
43// clang-format off
44namespace device { struct cpu; struct gpu; } // namespace device
45// clang-format on
46
47namespace internal
48{
49template <typename Ret>
50struct apply
51{
52 //----------------------------------------------------------------------------------//
53 // invoke a function with a tuple
54 //
55 template <typename Fn, typename Tuple, size_t... Idx>
56 static TIMEMORY_INLINE Ret invoke(Fn&& __f, Tuple&& __t, index_sequence<Idx...>)
57 {
58 return __f(std::get<Idx>(std::forward<Tuple>(__t))...);
59 }
60
61 //----------------------------------------------------------------------------------//
62 // prefix with _sep
63 //
64 template <typename SepT, typename Arg,
65 enable_if_t<std::is_same<Ret, std::string>::value, char> = 0>
66 static TIMEMORY_INLINE Ret join_tail(std::stringstream& _ss, const SepT& _sep,
67 Arg&& _arg)
68 {
69 _ss << _sep << std::forward<Arg>(_arg);
70 return _ss.str();
71 }
72
73 //----------------------------------------------------------------------------------//
74 // prefix with _sep
75 //
76 template <typename SepT, typename Arg, typename... Args,
77 enable_if_t<std::is_same<Ret, std::string>::value, char> = 0>
78 static TIMEMORY_INLINE Ret join_tail(std::stringstream& _ss, const SepT& _sep,
79 Arg&& _arg, Args&&... __args)
80 {
81 _ss << _sep << std::forward<Arg>(_arg);
82 return join_tail<SepT, Args...>(_ss, _sep, std::forward<Args>(__args)...);
83 }
84
85 //----------------------------------------------------------------------------------//
86 // don't prefix
87 //
88 template <typename SepT, typename Arg,
89 enable_if_t<std::is_same<Ret, std::string>::value, char> = 0>
90 static TIMEMORY_INLINE Ret join(std::stringstream& _ss, const SepT&, Arg&& _arg)
91 {
92 _ss << std::forward<Arg>(_arg);
93 return _ss.str();
94 }
95
96 //----------------------------------------------------------------------------------//
97 // don't prefix
98 //
99 template <typename SepT, typename Arg, typename... Args,
100 enable_if_t<std::is_same<Ret, std::string>::value, char> = 0,
101 enable_if_t<(sizeof...(Args) > 0), int> = 0>
102 static TIMEMORY_INLINE Ret join(std::stringstream& _ss, const SepT& _sep, Arg&& _arg,
103 Args&&... __args)
104 {
105 _ss << std::forward<Arg>(_arg);
106 return join_tail<SepT, Args...>(_ss, _sep, std::forward<Args>(__args)...);
107 }
108
109 //----------------------------------------------------------------------------------//
110};
111
112//======================================================================================//
113
114template <>
115struct apply<void>
116{
117 using Ret = void;
118
119 //----------------------------------------------------------------------------------//
120
121 template <typename Tp, typename Tail>
122 struct get_index_of;
123
124 template <typename Tp, typename... Tail>
125 struct get_index_of<Tp, std::tuple<Tp, Tail...>>
126 {
127 static constexpr int value = 0;
128 };
129
130 template <typename Tp, typename... Tail>
131 struct get_index_of<Tp, std::tuple<Tp*, Tail...>>
132 {
133 static constexpr int value = 0;
134 };
135
136 template <typename Tp, typename... Tail>
137 struct get_index_of<Tp, std::tuple<Tp&, Tail...>>
138 {
139 static constexpr int value = 0;
140 };
141
142 template <typename Tp, typename Head, typename... Tail>
143 struct get_index_of<Tp, std::tuple<Head, Tail...>>
144 {
145 static constexpr int value = 1 + get_index_of<Tp, std::tuple<Tail...>>::value;
146 };
147
148 template <typename Tp, typename... Tail>
149 struct get_index_of<Tp, std::tuple<Tail...>>
150 {
151 static_assert(sizeof...(Tail) != 0, "Error! Type not found!");
152 };
153
154 //----------------------------------------------------------------------------------//
155 // invoke a function with a tuple
156 //
157 template <typename Fn, typename Tuple, size_t... Idx>
158 static TIMEMORY_INLINE Ret invoke(Fn&& __f, Tuple&& __t, index_sequence<Idx...>)
159 {
160 __f(std::get<Idx>(std::forward<Tuple>(__t))...);
161 }
162
163 //----------------------------------------------------------------------------------//
164 // temporary construction
165 //
166 template <typename Type, typename... Args>
167 static TIMEMORY_INLINE void construct(Args&&... _args)
168 {
169 Type(std::forward<Args>(_args)...);
170 }
171
172 //----------------------------------------------------------------------------------//
173 // temporary construction
174 //
175 template <typename Type, typename... Args, size_t... Idx>
176 static TIMEMORY_INLINE void construct_tuple(std::tuple<Args...>&& _args,
177 index_sequence<Idx>...)
178 {
179 construct<Type>(std::get<Idx>(_args)...);
180 }
181
182 //----------------------------------------------------------------------------------//
183
184 template <template <typename> class Access, typename Tuple, typename... Args,
185 size_t... Idx>
186 static TIMEMORY_INLINE void unroll_access(Tuple&& __t, index_sequence<Idx...>,
187 Args&&... __args)
188 {
189 TIMEMORY_FOLD_EXPRESSION(Access<decay_t<decltype(std::get<Idx>(__t))>>(
190 std::forward<decltype(std::get<Idx>(__t))>(std::get<Idx>(__t)),
191 std::forward<Args>(__args)...));
192 }
193
194 //----------------------------------------------------------------------------------//
195
196 template <typename Access, typename Tuple, typename... Args, size_t... Idx>
197 static TIMEMORY_INLINE void variadic_1d(Tuple&& __t, Args&&... _args,
198 index_sequence<Idx...>)
199 {
201 construct<typename std::tuple_element<Idx, Access>::type>(
202 std::get<Idx>(__t), std::forward<Args>(_args)...));
203 }
204
205 //----------------------------------------------------------------------------------//
206
207 template <typename Access, typename TupleA, typename TupleB, typename... Args,
208 size_t... Idx>
209 static TIMEMORY_INLINE void variadic_2d(TupleA&& __a, TupleB&& __b, Args&&... _args,
210 index_sequence<Idx...>)
211 {
213 construct<typename std::tuple_element<Idx, Access>::type>(
214 std::get<Idx>(__a), std::get<Idx>(__b), std::forward<Args>(_args)...));
215 }
216
217 //----------------------------------------------------------------------------------//
218
219 template <template <typename> class Access, typename Tuple, typename... Args,
220 size_t... Idx>
221 static TIMEMORY_INLINE void type_access(index_sequence<Idx...>, Args&&... __args)
222 {
224 Access<decay_t<typename std::tuple_element<Idx, Tuple>::type>>(
225 std::forward<Args>(__args)...));
226 }
227
228 //----------------------------------------------------------------------------------//
229
230 template <typename Access, typename Tuple, typename... Args, size_t... Idx>
231 static TIMEMORY_INLINE void apply_access_with_indices(Tuple&& __t,
232 index_sequence<Idx...>,
233 Args&&... __args)
234 {
235 // call constructor
236 TIMEMORY_FOLD_EXPRESSION(decay_t<typename std::tuple_element<Idx, Access>::type>(
237 Idx, sizeof...(Idx),
238 std::forward<decltype(std::get<Idx>(__t))>(std::get<Idx>(__t)),
239 std::forward<Args>(__args)...));
240 }
241
242 //----------------------------------------------------------------------------------//
243
244 template <typename Access, typename TupleA, typename TupleB, typename... Args,
245 size_t... Idx>
246 static TIMEMORY_INLINE void apply_access2(TupleA&& __ta, TupleB&& __tb,
247 index_sequence<Idx...>, Args&&... __args)
248 {
249 // call constructor
250 TIMEMORY_FOLD_EXPRESSION(decay_t<typename std::tuple_element<Idx, Access>::type>(
251 std::forward<decltype(std::get<Idx>(__ta))>(std::get<Idx>(__ta)),
252 std::forward<decltype(std::get<Idx>(__tb))>(std::get<Idx>(__tb)),
253 std::forward<Args>(__args)...));
254 }
255
256 //----------------------------------------------------------------------------------//
257 // unroll
258 template <size_t N, typename Device, typename Func, typename... Args,
259 typename std::enable_if<
260 (N == 1 && std::is_same<Device, device::gpu>::value), char>::type = 0>
261 TIMEMORY_LAMBDA static void unroll(Func&& __func, Args&&... __args)
262 {
263 std::forward<Func>(__func)(std::forward<Args>(__args)...);
264 }
265
266 template <size_t N, typename Device, typename Func, typename... Args,
267 typename std::enable_if<(N > 1 && std::is_same<Device, device::gpu>::value),
268 char>::type = 0>
269 TIMEMORY_LAMBDA static void unroll(Func&& __func, Args&&... __args)
270 {
271 std::forward<Func>(__func)(std::forward<Args>(__args)...);
272 unroll<N - 1, Device, Func, Args...>(std::forward<Func>(__func),
273 std::forward<Args>(__args)...);
274 }
275
276 //----------------------------------------------------------------------------------//
277 // unroll
278 template <size_t N, typename Device, typename Func, typename... Args,
279 typename std::enable_if<
280 (N == 1 && std::is_same<Device, device::cpu>::value), int>::type = 0>
281 static TIMEMORY_INLINE void unroll(Func&& __func, Args&&... __args)
282 {
283 std::forward<Func>(__func)(std::forward<Args>(__args)...);
284 }
285
286 template <size_t N, typename Device, typename Func, typename... Args,
287 typename std::enable_if<(N > 1 && std::is_same<Device, device::cpu>::value),
288 int>::type = 0>
289 static TIMEMORY_INLINE void unroll(Func&& __func, Args&&... __args)
290 {
291 std::forward<Func>(__func)(std::forward<Args>(__args)...);
292 unroll<N - 1, Device, Func, Args...>(std::forward<Func>(__func),
293 std::forward<Args>(__args)...);
294 }
295
296 //----------------------------------------------------------------------------------//
297};
298
299//======================================================================================//
300
301} // namespace internal
302
303//======================================================================================//
304//
305// Declaration
306//
307//======================================================================================//
308
309namespace mpl
310{
311template <typename Ret>
312struct apply;
313
314//======================================================================================//
315//
316// apply --> std::string
317//
318//======================================================================================//
319
320template <>
322{
323 using Ret = std::string;
324 using string_t = std::string;
325 using string_tuple_t = std::tuple<std::string>;
326
327 //----------------------------------------------------------------------------------//
328 // Helper
329 //----------------------------------------------------------------------------------//
330
331 template <typename Tp, bool _Val = true, typename Up = int,
332 typename Dt = typename std::remove_const<decay_t<Tp>>::type>
333 using if_string_t = enable_if_t<std::is_same<Dt, char*>::value == _Val, Up>;
334
335 //----------------------------------------------------------------------------------//
336
337 template <typename SepT, typename... Args, typename ReturnT = Ret,
338 size_t N = sizeof...(Args), enable_if_t<(N > 0), char> = 0>
339 static TIMEMORY_INLINE ReturnT join(SepT&& separator, Args&&... __args) noexcept
340 {
341 std::stringstream ss;
342 ss << std::boolalpha;
343 return internal::apply<Ret>::template join<SepT, Args...>(
344 std::ref(ss), std::forward<SepT>(separator), std::forward<Args>(__args)...);
345 }
346
347 //----------------------------------------------------------------------------------//
348
349 template <typename SepT, typename Arg, if_string_t<Arg, true> = 0>
350 static TIMEMORY_INLINE Ret join(SepT&&, Arg&& _arg) noexcept
351 {
352 return std::forward<Arg>(_arg);
353 }
354
355 //----------------------------------------------------------------------------------//
356
357 template <typename SepT, typename Arg, if_string_t<Arg, false> = 0>
358 static TIMEMORY_INLINE Ret join(SepT&&, Arg&& _arg) noexcept
359 {
360 std::stringstream ss;
361 ss << _arg;
362 return ss.str();
363 }
364
365 //----------------------------------------------------------------------------------//
366
367 static TIMEMORY_INLINE Ret join(const string_t&) noexcept { return Ret{}; }
368 static TIMEMORY_INLINE Ret join(const char) noexcept { return Ret{}; }
369
370 //----------------------------------------------------------------------------------//
371};
372
373//======================================================================================//
374//
375// apply --> generic
376//
377//======================================================================================//
378
379template <typename Ret>
380struct apply
381{
383
384 //----------------------------------------------------------------------------------//
385 // invoke a function
386 //
387 template <typename Fn, typename... Args, size_t N = sizeof...(Args)>
388 static TIMEMORY_INLINE Ret invoke(Fn&& __f, Args&&... __args) noexcept
389 {
390 return __f(std::forward<Args>(__args)...);
391 }
392
393 //----------------------------------------------------------------------------------//
394 // invoke a function with a tuple
395 //
396 template <typename Fn, template <typename...> class Tuple, typename... Args,
397 size_t N = sizeof...(Args)>
398 static TIMEMORY_INLINE Ret invoke(Fn&& __f, Tuple<Args...>&& __t) noexcept
399 {
400 using Tuple_t = Tuple<Args...>;
401 return internal::apply<Ret>::template invoke<Fn, Tuple_t>(
402 std::forward<Fn>(__f), std::forward<Tuple_t>(__t), make_index_sequence<N>{});
403 }
404
405 //----------------------------------------------------------------------------------//
406
407 template <typename SepT, typename Tuple, size_t... Idx>
408 static TIMEMORY_INLINE string_t join(SepT&& separator, Tuple&& __tup,
409 index_sequence<Idx...>) noexcept
410 {
411 return apply<string_t>::join(separator, std::get<Idx>(__tup)...);
412 }
413};
414
415//======================================================================================//
416//
417// apply --> std::tuple<std::string>
418//
419//======================================================================================//
420
421template <>
422struct apply<std::tuple<std::string>>
423{
424 using string_t = std::string;
425 using Ret = string_t;
426 using apply_v = apply<string_t>;
427
428 //----------------------------------------------------------------------------------//
429 // implementation for label + entry join
430 //
431 struct impl
432 {
433 template <typename LabelSep, typename EntrySep, typename LabelTup,
434 typename EntryTup, size_t... Idx>
435 static Ret join(LabelSep&& _label_sep, EntrySep&& _entry_sep,
436 LabelTup&& _label_tup, EntryTup&& _entry_tup,
437 index_sequence<Idx...>) noexcept
438 {
439 return apply_v::join(std::forward<LabelSep>(_label_sep),
440 apply_v::join(std::forward<EntrySep>(_entry_sep),
441 std::get<Idx>(_label_tup),
442 std::get<Idx>(_entry_tup))...);
443 }
444 };
445
446 //----------------------------------------------------------------------------------//
447 // join a tuple of labels with entries
448 //
449 template <typename LabelSep, typename EntrySep, typename LabelTup, typename EntryTup,
450 size_t N = std::tuple_size<decay_t<LabelTup>>::value,
451 enable_if_t<(N > 0), int> = 0>
452 static TIMEMORY_INLINE Ret join(LabelSep&& _label_sep, EntrySep&& _entry_sep,
453 LabelTup&& _label_tup, EntryTup&& _entry_tup) noexcept
454 {
455 // clang-format off
456 return impl::join(std::forward<LabelSep>(_label_sep),
457 std::forward<EntrySep>(_entry_sep),
458 std::forward<LabelTup>(_label_tup),
459 std::forward<EntryTup>(_entry_tup),
460 make_index_sequence<N>{});
461 // clang-format on
462 }
463
464 //----------------------------------------------------------------------------------//
465 // join a tuple of labels with entries
466 //
467 template <typename LabelSep, typename EntrySep, typename LabelTup, typename EntryTup,
468 size_t N = std::tuple_size<decay_t<LabelTup>>::value,
469 enable_if_t<N == 0, int> = 0>
470 static TIMEMORY_INLINE Ret join(LabelSep&&, EntrySep&&, LabelTup&&,
471 EntryTup&&) noexcept
472 {
473 return "";
474 }
475
476 //----------------------------------------------------------------------------------//
477};
478
479//======================================================================================//
480//
481// apply --> void
482//
483//======================================================================================//
484
485template <>
486struct apply<void>
487{
488 using Ret = void;
489
490 //----------------------------------------------------------------------------------//
491
492 template <size_t I, typename A>
493 using Access_t = typename std::tuple_element<I, A>::type;
494
495 //----------------------------------------------------------------------------------//
496 // invoke a function
497 //
498 template <typename Fn, typename... Args, size_t N = sizeof...(Args)>
499 static TIMEMORY_INLINE Ret invoke(Fn&& __f, Args&&... __args) noexcept
500 {
501 __f(std::forward<Args>(__args)...);
502 }
503
504 //----------------------------------------------------------------------------------//
505 // invoke a function with a tuple
506 //
507 template <typename Fn, template <typename...> class Tuple, typename... Args,
508 size_t N = sizeof...(Args)>
509 static TIMEMORY_INLINE Ret invoke(Fn&& __f, Tuple<Args...>&& __t) noexcept
510 {
511 using Tuple_t = Tuple<Args...>;
512 internal::apply<Ret>::template invoke<Fn, Tuple_t>(
513 std::forward<Fn>(__f), std::forward<Tuple_t>(__t), make_index_sequence<N>{});
514 }
515
516 //----------------------------------------------------------------------------------//
517 // per-element addition
518 //
519 template <typename Tuple, size_t N = std::tuple_size<Tuple>::value>
520 static TIMEMORY_INLINE void plus(Tuple& _lhs, const Tuple& _rhs) noexcept
521 {
522 math::plus(_lhs, _rhs);
523 }
524
525 //----------------------------------------------------------------------------------//
526 // per-element subtraction
527 //
528 template <typename Tuple, size_t N = std::tuple_size<Tuple>::value>
529 static TIMEMORY_INLINE void minus(Tuple& _lhs, const Tuple& _rhs) noexcept
530 {
531 math::minus(_lhs, _rhs);
532 }
533
534 //----------------------------------------------------------------------------------//
535
536 template <size_t N, typename Device, typename Func, typename... Args,
538 TIMEMORY_LAMBDA static void unroll(Func&& __func, Args&&... __args) noexcept
539 {
540 internal::apply<void>::template unroll<N, Device, Func, Args...>(
541 std::forward<Func>(__func), std::forward<Args>(__args)...);
542 }
543
544 //----------------------------------------------------------------------------------//
545
546 template <size_t N, typename Device, typename Func, typename... Args,
548 static TIMEMORY_INLINE void unroll(Func&& __func, Args&&... __args) noexcept
549 {
550 internal::apply<void>::template unroll<N, Device, Func, Args...>(
551 std::forward<Func>(__func), std::forward<Args>(__args)...);
552 }
553
554 //----------------------------------------------------------------------------------//
555 //
556 // N > 0
557 //
558 //----------------------------------------------------------------------------------//
559
560 template <typename Tp, typename Value>
561 static TIMEMORY_INLINE auto set_value_fold(Tp&& _t, int, Value&& _v) noexcept
562 -> decltype(std::forward<Tp>(_t) = std::forward<Value>(_v), void())
563 {
564 std::forward<Tp>(_t) = std::forward<Value>(_v);
565 }
566
567 template <typename Tp, typename Value>
568 static TIMEMORY_INLINE void set_value_fold(Tp&&, long, Value&&) noexcept
569 {}
570
571 template <typename Tuple, typename Value, size_t... Idx>
572 static TIMEMORY_INLINE void set_value_fold(Tuple&& _t, Value&& _v,
573 index_sequence<Idx...>) noexcept
574 {
576 set_value_fold(std::get<Idx>(_t), 0, std::forward<Value>(_v)));
577 }
578
579 //----------------------------------------------------------------------------------//
580
581 template <typename Tuple, typename Value>
582 static TIMEMORY_INLINE void set_value(Tuple&& _t, Value&& _v) noexcept
583 {
584 constexpr auto N = std::tuple_size<decay_t<Tuple>>::value;
585 set_value_fold(std::forward<Tuple>(_t), std::forward<Value>(_v),
587 }
588
589 //----------------------------------------------------------------------------------//
590
591 template <typename Access, typename Tuple, size_t... Idx, typename... Args>
592 static TIMEMORY_INLINE void access_fold(Tuple&& _t, index_sequence<Idx...>,
593 Args&&... _args)
594 {
596 Access_t<Idx, Access>(std::get<Idx>(_t), std::forward<Args>(_args)...));
597 }
598
599 //----------------------------------------------------------------------------------//
600
601 template <typename Access, typename Tuple, typename... Args>
602 static TIMEMORY_INLINE void access(Tuple&& __t, Args&&... __args) noexcept
603 {
604 constexpr auto N = std::tuple_size<decay_t<Access>>::value;
605 constexpr auto Nt = std::tuple_size<decay_t<Tuple>>::value;
606 static_assert(N == Nt, "Cannot fold Access from Tuple because sizes differ");
607 access_fold<Access>(std::forward<Tuple>(__t), std::make_index_sequence<N>{},
608 std::forward<Args>(__args)...);
609 }
610
611 //----------------------------------------------------------------------------------//
612
613 template <typename Access, size_t... Idx, typename... Args>
614 static TIMEMORY_INLINE auto get_fold(index_sequence<Idx...>, Args&&... _args)
615 {
616 return std::make_tuple(
617 Access_t<Idx, Access>::get(std::forward<Args>(_args)...)...);
618 }
619
620 //----------------------------------------------------------------------------------//
621
622 template <typename Access, typename... Args>
623 static TIMEMORY_INLINE auto get(Args&&... __args)
624 {
625 constexpr auto N = std::tuple_size<decay_t<Access>>::value;
626 return get_fold<Access>(std::make_index_sequence<N>{},
627 std::forward<Args>(__args)...);
628 }
629
630 //----------------------------------------------------------------------------------//
631
632 template <typename Access, typename Tuple, typename... Args>
633 static TIMEMORY_INLINE void access_with_indices(Tuple&& __t,
634 Args&&... __args) noexcept
635 {
636 constexpr auto N = std::tuple_size<decay_t<Tuple>>::value;
637 internal::apply<void>::template apply_access_with_indices<Access, Tuple, Args...>(
638 std::forward<Tuple>(__t), make_index_sequence<N>{},
639 std::forward<Args>(__args)...);
640 }
641
642 //----------------------------------------------------------------------------------//
643
644 template <typename Access, typename TupleA, typename TupleB, typename... Args>
645 static TIMEMORY_INLINE void access2(TupleA&& __ta, TupleB&& __tb,
646 Args&&... __args) noexcept
647 {
648 constexpr size_t N = std::tuple_size<decay_t<Access>>::value;
649 constexpr size_t Na = std::tuple_size<decay_t<TupleA>>::value;
650 constexpr size_t Nb = std::tuple_size<decay_t<TupleB>>::value;
651 static_assert(Na == Nb, "tuple A size must match tuple B size");
652 internal::apply<void>::template apply_access2<Access, TupleA, TupleB, Args...>(
653 std::forward<TupleA>(__ta), std::forward<TupleB>(__tb),
654 make_index_sequence<N>{}, std::forward<Args>(__args)...);
655 }
656
657 //----------------------------------------------------------------------------------//
658
659 template <template <typename> class Access, typename Tuple, typename... Args>
660 static TIMEMORY_INLINE void unroll_access(Tuple&& __t, Args&&... __args) noexcept
661 {
662 constexpr size_t N = std::tuple_size<decay_t<Tuple>>::value;
663 internal::apply<void>::template unroll_access<Access, Tuple, Args...>(
664 std::forward<Tuple>(__t), make_index_sequence<N>{},
665 std::forward<Args>(__args)...);
666 }
667
668 //----------------------------------------------------------------------------------//
669
670 template <template <typename> class Access, typename Tuple, typename... Args>
671 static TIMEMORY_INLINE void type_access(Args&&... __args) noexcept
672 {
673 constexpr size_t N = std::tuple_size<decay_t<Tuple>>::value;
674 internal::apply<void>::template type_access<Access, Tuple, Args...>(
675 make_index_sequence<N>{}, std::forward<Args>(__args)...);
676 }
677
678 //----------------------------------------------------------------------------------//
679};
680//
681} // namespace mpl
682} // namespace tim
#define TIMEMORY_LAMBDA
Definition: attributes.hpp:177
STL namespace.
Tp & plus(Tp &, const Up &)
Definition: plus.hpp:106
Tp & minus(Tp &, const Up &)
Definition: minus.hpp:98
auto join(const char *sep, Arg &&arg, Args &&... args)
Definition: declaration.hpp:74
Ret invoke(string_view_t &&label, Func &&func, Args &&... args)
Definition: invoker.hpp:39
Definition: kokkosp.cpp:39
std::make_integer_sequence< size_t, Num > make_index_sequence
Alias template make_index_sequence.
Definition: types.hpp:182
std::array< char *, 4 > _args
std::string string_t
Definition: utility.hpp:98
typename std::decay< T >::type decay_t
Alias template for decay.
Definition: types.hpp:194
typename std::enable_if< B, T >::type enable_if_t
Alias template for enable_if.
Definition: types.hpp:190
tim::mpl::apply< std::string > string
Definition: macros.hpp:53
std::integer_sequence< size_t, Idx... > index_sequence
Alias template index_sequence.
Definition: types.hpp:178
static void access_with_indices(Tuple &&__t, Args &&... __args) noexcept
Definition: apply.hpp:633
static auto set_value_fold(Tp &&_t, int, Value &&_v) noexcept -> decltype(std::forward< Tp >(_t)=std::forward< Value >(_v), void())
Definition: apply.hpp:561
static void unroll_access(Tuple &&__t, Args &&... __args) noexcept
Definition: apply.hpp:660
static void access2(TupleA &&__ta, TupleB &&__tb, Args &&... __args) noexcept
Definition: apply.hpp:645
static void set_value_fold(Tuple &&_t, Value &&_v, index_sequence< Idx... >) noexcept
Definition: apply.hpp:572
static Ret invoke(Fn &&__f, Args &&... __args) noexcept
Definition: apply.hpp:499
static void access(Tuple &&__t, Args &&... __args) noexcept
Definition: apply.hpp:602
static void set_value_fold(Tp &&, long, Value &&) noexcept
Definition: apply.hpp:568
static auto get(Args &&... __args)
Definition: apply.hpp:623
typename std::tuple_element< I, A >::type Access_t
Definition: apply.hpp:493
static void access_fold(Tuple &&_t, index_sequence< Idx... >, Args &&... _args)
Definition: apply.hpp:592
static void set_value(Tuple &&_t, Value &&_v) noexcept
Definition: apply.hpp:582
static auto get_fold(index_sequence< Idx... >, Args &&... _args)
Definition: apply.hpp:614
static void minus(Tuple &_lhs, const Tuple &_rhs) noexcept
Definition: apply.hpp:529
static Ret invoke(Fn &&__f, Tuple< Args... > &&__t) noexcept
Definition: apply.hpp:509
static void unroll(Func &&__func, Args &&... __args) noexcept
Definition: apply.hpp:538
static void plus(Tuple &_lhs, const Tuple &_rhs) noexcept
Definition: apply.hpp:520
static void type_access(Args &&... __args) noexcept
Definition: apply.hpp:671
static string_t join(SepT &&separator, Tuple &&__tup, index_sequence< Idx... >) noexcept
Definition: apply.hpp:408
static Ret invoke(Fn &&__f, Args &&... __args) noexcept
Definition: apply.hpp:388
std::string string_t
Definition: apply.hpp:382
static Ret invoke(Fn &&__f, Tuple< Args... > &&__t) noexcept
Definition: apply.hpp:398
#define TIMEMORY_FOLD_EXPRESSION(...)
Definition: types.hpp:56