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.
types.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 deal
9// in the Software without restriction, including without limitation the rights
10// 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 all
15// 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 FROM,
22// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23// SOFTWARE.
24
25/** \file mpl/types.hpp
26 * \headerfile mpl/types.hpp "timemory/mpl/types.hpp"
27 *
28 * This is a declaration of all the operation structs.
29 * Care should be taken to make sure that this includes a minimal
30 * number of additional headers.
31 *
32 */
33
34#pragma once
35
36#include "timemory/api.hpp"
39
40#include <cstdint>
41#include <functional>
42#include <iostream>
43#include <string>
44#include <type_traits>
45#include <vector>
46
47//======================================================================================//
48//
49namespace tim
50{
51//
52//--------------------------------------------------------------------------------------//
53//
54#if defined(TIMEMORY_USE_DEPRECATED)
55//
56template <typename TupleT, typename ListT>
57class [[deprecated("Use component_bundle<T..., L*...>")]] component_hybrid;
58//
59template <typename TupleT, typename ListT>
60class [[deprecated("Use auto_bundle<T..., L*...>")]] auto_hybrid;
61//
62#endif
63//
64//======================================================================================//
65// type-traits for customization
66//
67namespace trait
68{
69//
70using default_record_statistics_type = TIMEMORY_DEFAULT_STATISTICS_TYPE;
71//
72template <typename TraitT>
73std::string
74as_string();
75//
76/// \struct tim::trait::apply
77/// \brief generic functions for setting/accessing static properties on types
78template <template <typename...> class TraitT, typename... CommonT>
79struct apply
80{
81 //
82 TIMEMORY_DEFAULT_OBJECT(apply)
83 //
84 template <typename... Types, typename... Args>
85 static inline void set(Args&&... args)
86 {
87 TIMEMORY_FOLD_EXPRESSION(
88 TraitT<Types, CommonT...>::set(std::forward<Args>(args)...));
89 }
90 //
91 template <typename... Types, typename... Args>
92 static inline auto get(Args&&... args)
93 {
94 return std::make_tuple(
95 TraitT<Types, CommonT...>::get(std::forward<Args>(args)...)...);
96 }
97 //
98 template <typename... Types>
99 inline bool operator()(type_list<Types...>)
100 {
101 bool _ret = true;
102 TIMEMORY_FOLD_EXPRESSION(_ret = _ret && TraitT<Types>::get());
103 return _ret;
104 }
105}; //
106//
107template <typename T>
108struct base_has_accum;
109
110template <typename T>
111struct base_has_last;
112
113template <typename T>
114struct is_available;
115
116template <typename T>
117struct data;
118
119template <typename T, bool>
120struct component_value_type;
121
122template <typename T>
123struct collects_data;
124
125template <typename T>
126using runtime_configurable = concepts::is_runtime_configurable<T>;
127
128template <typename T = void>
129struct supports_runtime_enabled;
130
131template <typename T = void>
132struct default_runtime_enabled;
133
134template <typename T = void>
135struct runtime_enabled;
136
137template <typename T>
138struct record_max;
139
140template <typename T>
141struct array_serialization;
142
143template <typename T>
144struct requires_prefix;
145
146template <typename T>
147struct custom_label_printing;
148
149template <typename T>
150struct custom_unit_printing;
151
152template <typename T>
153struct start_priority;
154
155template <typename T>
156struct stop_priority;
157
158template <typename T>
159struct fini_priority;
160
161template <typename T>
162struct is_timing_category;
163
164template <typename T>
165struct is_memory_category;
166
167template <typename T>
168struct uses_timing_units;
169
170template <typename T>
171struct uses_memory_units;
172
173template <typename T>
174struct uses_percent_units;
175
176template <typename T>
177struct requires_json;
178
179template <typename T>
180struct is_component;
181
182template <typename T, typename Tag = void>
183struct api_components;
184
185template <typename T>
186struct component_apis;
187
188template <typename T>
189struct is_gotcha;
190
191template <typename T>
192struct is_user_bundle;
193
194template <typename T, typename Tuple>
195struct supports_args;
196
197template <typename T>
198struct supports_custom_record;
199
200template <typename T>
201struct iterable_measurement;
202
203template <typename T>
204struct secondary_data;
205
206template <typename T>
207struct thread_scope_only;
208
209template <typename T>
210struct custom_serialization;
211
212template <typename T>
213struct record_statistics;
214
215template <typename T>
216struct statistics;
217
218template <typename T>
219struct permissive_statistics;
220
221template <typename T>
222struct sampler;
223
224template <typename T>
225struct file_sampler;
226
227template <typename T>
228struct units;
229
230template <typename T>
231struct echo_enabled;
232
233template <typename Api = TIMEMORY_API>
234struct api_input_archive;
235
236template <typename Api = TIMEMORY_API>
237struct api_output_archive;
238
239template <typename T, typename Api = TIMEMORY_API>
240struct input_archive;
241
242template <typename T, typename Api = TIMEMORY_API>
243struct output_archive;
244
245template <typename T>
246struct pretty_archive;
247
248template <typename T>
249struct archive_extension;
250
251template <typename T>
252struct report;
253
254template <typename T>
255struct report_count;
256
257template <typename T>
258struct report_depth;
259
260template <typename T>
261struct report_metric_name;
262
263template <typename T>
264struct report_units;
265
266template <typename T>
267struct report_sum;
268
269template <typename T>
270struct report_mean;
271
272template <typename T>
273struct report_statistics;
274
275template <typename T>
276struct report_self;
277
278template <typename T>
279struct ompt_handle;
280
281template <typename T>
282struct supports_flamegraph;
283
284template <typename T>
285struct derivation_types;
286
287template <int OpT, typename T>
288struct python_args;
289
290template <typename T>
291struct cache;
292
293template <typename T, typename V = trait::data<T>>
294struct generates_output;
295
296template <typename T>
297struct uses_storage;
298
299template <typename T>
300struct tree_storage;
301
302template <typename T>
303struct flat_storage;
304
305template <typename T>
306struct timeline_storage;
307
308template <typename T, typename V = trait::data<T>, typename A = trait::uses_storage<T>>
309struct uses_value_storage;
310
311template <typename ApiT>
312struct perfetto_category;
313
314//--------------------------------------------------------------------------------------//
315//
316// ALIASES
317//
318//--------------------------------------------------------------------------------------//
319//
320template <typename T>
321using input_archive_t = typename input_archive<T, TIMEMORY_API>::type;
322
323template <typename T>
324using output_archive_t = typename output_archive<T, TIMEMORY_API>::type;
325//
326//--------------------------------------------------------------------------------------//
327/// \struct tim::trait::is_available
328/// \brief trait that signifies that an implementation for the component is available.
329/// When this is set to false, the variadic component bundlers like \ref component_tuple
330/// will silently filter out this type from the template parameters, e.g.
331///
332/// \code{.cpp}
333/// TIMEMORY_DECLARE_COMPONENT(foo)
334/// TIMEMORY_DECLARE_COMPONENT(bar)
335///
336/// namespace tim {
337/// namespace trait {
338/// template <>
339/// struct is_available<component::bar> : false_type {};
340/// }
341/// }
342/// \endcode
343///
344/// will cause these two template instantiations to become identical:
345///
346/// \code{.cpp}
347/// using A_t = component_tuple<foo>;
348/// using B_t = component_tuple<foo, bar>;
349/// \endcode
350///
351/// and a definition of 'bar' will not be required for compilation.
352///
353template <typename T>
354struct is_available : TIMEMORY_DEFAULT_AVAILABLE
355{};
356
357template <typename T>
358struct is_available<T*> : is_available<std::remove_pointer_t<T>>
359{};
360
361template <typename T>
362using is_available_t = typename is_available<T>::type;
363//
364} // namespace trait
365
366//======================================================================================//
367// generic helpers that can/should be inherited from
368//
369namespace policy
370{
371/// \struct tim::policy::instance_tracker
372/// \brief Inherit from this policy to add reference counting support. Useful if
373/// you want to turn a global setting on/off when the number of components taking
374/// measurements has hit zero (e.g. all instances of component have called stop).
375/// Simply provides member functions and data values, increment/decrement is not
376/// automatically performed.
377/// In general, call instance_tracker::start or instance_tracker::stop inside
378/// of the components constructor if a component collects data and is using
379/// storage because instance(s) will be in the call-graph and thus, the instance
380/// count will always be > 0. Set the second template parameter to true if thread-local
381/// instance tracking is desired.
382/// \code{.cpp}
383/// struct foo
384/// : public base<foo, void>
385/// , private policy::instance_tracker<foo, false>
386/// {
387/// using value_type = void;
388/// using instance_tracker_t = policy::instance_tracker<foo, false>;
389///
390/// void start()
391/// {
392/// auto cnt = instance_tracker_t::start();
393/// if(cnt == 0)
394/// // start something
395/// }
396///
397/// void stop()
398/// {
399/// auto cnt = instance_tracker_t::stop();
400/// if(cnt == 0)
401/// // stop something
402/// }
403/// };
404/// \endcode
405template <typename T, bool WithThreads = true>
406struct instance_tracker;
407
408/// \struct tim::policy::record_statistics
409/// \brief Specification of how to accumulate statistics. This will not be used
410/// unless \ref tim::trait::statistics has been assigned a type and \ref
411/// tim::trait::record_statistics is true. Set \ref tim::trait::permissive_statistics to
412/// allow implicit conversions, e.g. int -> size_t.
413/// \code{.cpp}
414/// template <typename CompT, typename Tp>
415/// struct record_statistics
416/// {
417/// using type = Tp;
418/// using component_type = CompT;
419/// using statistics_type = statistics<type>;
420///
421/// static void apply(statistics_type& stats, const component_type& obj)
422/// {
423/// // example:
424/// // typeid(stats) is tim::statistics<double>
425/// // obj.get() returns a double precision value
426/// stats += obj.get();
427/// }
428/// };
429/// \endcode
430template <typename CompT, typename T = typename trait::statistics<CompT>::type>
431struct record_statistics;
432
433/// \struct tim::policy::input_archive
434/// \brief Provides a static get() function which returns a shared pointer to an instance
435/// of the given archive format for input. Can also provides static functions for any
436/// global configuration options, if necessary.
437template <typename Archive, typename Api = TIMEMORY_API>
438struct input_archive;
439
440/// \struct tim::policy::output_archive
441/// \brief Provides a static get() function which return a shared pointer to an instance
442/// of the given archive format for output. Can also provide static functions for any
443/// global configuration options for the archive format. For example, the (pretty) JSON
444/// output archive supports specification of the precision, indentation length, and the
445/// indentation character.
446template <typename Archive, typename Api = TIMEMORY_API>
447struct output_archive;
448
449//--------------------------------------------------------------------------------------//
450//
451// ALIASES
452//
453//--------------------------------------------------------------------------------------//
454//
455template <typename T>
456using input_archive_t = input_archive<trait::input_archive_t<T>, TIMEMORY_API>;
457
458template <typename T>
459using output_archive_t = output_archive<trait::output_archive_t<T>, TIMEMORY_API>;
460//
461//--------------------------------------------------------------------------------------//
462//
463
464} // namespace policy
465//
466//--------------------------------------------------------------------------------------//
467//
468namespace impl
469{
470//--------------------------------------------------------------------------------------//
471//
472template <typename... Types>
473struct tuple_concat
474{
475 using type = std::tuple<Types...>;
476};
477
478//--------------------------------------------------------------------------------------//
479
480template <>
481struct tuple_concat<>
482{
483 using type = std::tuple<>;
484};
485
486//--------------------------------------------------------------------------------------//
487
488template <typename... Ts>
489struct tuple_concat<std::tuple<Ts...>>
490{
491 using type = std::tuple<Ts...>;
492};
493
494//--------------------------------------------------------------------------------------//
495
496template <typename... Ts0, typename... Ts1, typename... Rest>
497struct tuple_concat<std::tuple<Ts0...>, std::tuple<Ts1...>, Rest...>
498: tuple_concat<std::tuple<Ts0..., Ts1...>, Rest...>
499{};
500
501//--------------------------------------------------------------------------------------//
502//
503// type_list concatenation
504//
505//--------------------------------------------------------------------------------------//
506
507template <typename... Types>
508struct type_concat
509{
510 using type = type_list<Types...>;
511};
512
513//--------------------------------------------------------------------------------------//
514
515template <>
516struct type_concat<>
517{
518 using type = type_list<>;
519};
520
521//--------------------------------------------------------------------------------------//
522
523template <typename... Ts>
524struct type_concat<type_list<Ts...>>
525{
526 using type = type_list<Ts...>;
527};
528
529//--------------------------------------------------------------------------------------//
530
531template <typename... Ts0, typename... Ts1, typename... Rest>
532struct type_concat<type_list<Ts0...>, type_list<Ts1...>, Rest...>
533: type_concat<type_list<Ts0..., Ts1...>, Rest...>
534{};
535
536//--------------------------------------------------------------------------------------//
537///
538/// get the index of a type in expansion
539///
540template <typename Tp, typename Type>
541struct index_of;
542
543template <typename Tp, template <typename...> class Tuple, typename... Types>
544struct index_of<Tp, Tuple<Tp, Types...>>
545{
546 static constexpr size_t value = 0;
547};
548
549template <typename Tp, typename Head, template <typename...> class Tuple,
550 typename... Tail>
551struct index_of<Tp, Tuple<Head, Tail...>>
552{
553 static constexpr size_t value = 1 + index_of<Tp, Tuple<Tail...>>::value;
554};
555
556//--------------------------------------------------------------------------------------//
557
558} // namespace impl
559
560//======================================================================================//
561
562template <typename... Ts>
563using tuple_concat_t = typename impl::tuple_concat<Ts...>::type;
564
565template <typename... Ts>
566using type_concat_t = typename impl::type_concat<Ts...>::type;
567
568template <typename U>
569using remove_pointer_t = typename std::remove_pointer<U>::type;
570
571template <typename U>
572using add_pointer_t = conditional_t<(std::is_pointer<U>::value), U, U*>;
573
574template <typename Tp, typename Type>
575using index_of = impl::index_of<Tp, Type>;
576
577//======================================================================================//
578
579namespace impl
580{
581//--------------------------------------------------------------------------------------//
582
583template <typename T>
584struct unwrapper
585{
586 using type = T;
587};
588
589//--------------------------------------------------------------------------------------//
590
591template <template <typename...> class Tuple, typename... T>
592struct unwrapper<Tuple<T...>>
593{
594 using type = Tuple<T...>;
595};
596
597//--------------------------------------------------------------------------------------//
598
599template <template <typename...> class Tuple, typename... T>
600struct unwrapper<Tuple<Tuple<T...>>>
601{
602 using type = conditional_t<(std::is_same<Tuple<>, std::tuple<>>::value ||
603 std::is_same<Tuple<>, type_list<>>::value),
604 typename unwrapper<Tuple<T...>>::type, Tuple<Tuple<T...>>>;
605};
606
607//--------------------------------------------------------------------------------------//
608
609template <typename In, typename Out>
610struct convert
611{
612 using type = Out;
613
614 using input_type = In;
615 using output_type = Out;
616
617 static output_type apply(const input_type& _in)
618 {
619 return static_cast<output_type>(_in);
620 }
621};
622
623//--------------------------------------------------------------------------------------//
624
625template <template <typename...> class InTuple, typename... In,
626 template <typename...> class OutTuple, typename... Out>
627struct convert<InTuple<In...>, OutTuple<Out...>>
628{
629 using type = OutTuple<Out..., In...>;
630
631 using input_type = InTuple<In...>;
632 using output_type = OutTuple<Out...>;
633
634 static output_type apply(const input_type& _in)
635 {
636 output_type _out{};
637 TIMEMORY_FOLD_EXPRESSION(
638 std::get<index_of<Out, output_type>::value>(_out) =
639 static_cast<Out>(std::get<index_of<In, input_type>::value>(_in)));
640 return _out;
641 }
642};
643
644//--------------------------------------------------------------------------------------//
645
646template <typename ApiT, template <typename...> class InTuple,
647 template <typename...> class OutTuple, typename... In>
648struct convert<InTuple<ApiT, In...>, OutTuple<ApiT>>
649: convert<type_list<In...>, OutTuple<ApiT>>
650{};
651
652//--------------------------------------------------------------------------------------//
653
654template <template <typename...> class InTuple, typename... T>
655struct convert_each;
656
657template <template <typename...> class OutTuple, template <typename...> class InTuple,
658 typename... In>
659struct convert_each<OutTuple, InTuple<In...>>
660{
661 using type = std::tuple<OutTuple<In>...>;
662};
663
664//--------------------------------------------------------------------------------------//
665//
666#if defined(TIMEMORY_USE_DEPRECATED)
667//
668template <template <typename...> class LhsInT, typename... LhsIn,
669 template <typename...> class RhsInT, typename... RhsIn,
670 template <typename...> class LhsOutT, typename... LhsOut,
671 template <typename...> class RhsOutT, typename... RhsOut>
672struct convert<component_hybrid<LhsInT<LhsIn...>, RhsInT<RhsIn...>>,
673 auto_hybrid<LhsOutT<LhsOut...>, RhsOutT<RhsOut...>>>
674{
675 using type = auto_hybrid<LhsInT<LhsIn...>, RhsInT<RhsIn...>>;
676};
677
678//--------------------------------------------------------------------------------------//
679
680template <template <typename...> class LhsInT, typename... LhsIn,
681 template <typename...> class RhsInT, typename... RhsIn,
682 template <typename...> class LhsOutT, typename... LhsOut,
683 template <typename...> class RhsOutT, typename... RhsOut>
684struct convert<auto_hybrid<LhsInT<LhsIn...>, RhsInT<RhsIn...>>,
685 component_hybrid<LhsOutT<LhsOut...>, RhsOutT<RhsOut...>>>
686{
687 using type = component_hybrid<LhsInT<LhsIn...>, RhsInT<RhsIn...>>;
688};
689//
690#endif
691
692//--------------------------------------------------------------------------------------//
693
694template <template <typename> class CheckT, bool CheckV,
695 template <typename> class TransformT, typename... T>
696struct apply_transform;
697
698//--------------------------------------------------------------------------------------//
699
700/*template <typename In, typename Out>
701struct apply_transform<identity, true, identity, In, Out>
702{
703 using type = Out;
704};*/
705
706//--------------------------------------------------------------------------------------//
707
708template <template <typename> class CheckT, bool CheckV,
709 template <typename> class TransformT, typename... In, typename... Out>
710struct apply_transform<CheckT, CheckV, TransformT, type_list<In...>, type_list<Out...>>
711{
712 using type = type_list<Out..., conditional_t<CheckT<In>::value == CheckV,
713 typename TransformT<In>::type, In>...>;
714};
715
716//--------------------------------------------------------------------------------------//
717
718template <template <typename> class CheckT, bool CheckV,
719 template <typename> class TransformT, typename ApiT, typename... In>
720struct apply_transform<CheckT, CheckV, TransformT, type_list<ApiT, In...>,
721 type_list<ApiT>>
722: apply_transform<CheckT, CheckV, TransformT, type_list<In...>, type_list<ApiT>>
723{};
724
725//======================================================================================//
726// check if type is in expansion
727//
728template <typename... Tp>
729struct is_one_of
730{
731 static constexpr bool value = false;
732};
733
734template <typename F, typename S, template <typename...> class Tuple, typename... T>
735struct is_one_of<F, S, Tuple<T...>>
736{
737 static constexpr bool value =
738 std::is_same<F, S>::value || is_one_of<F, Tuple<T...>>::value;
739};
740
741template <typename F, typename S, template <typename...> class Tuple, typename... T>
742struct is_one_of<F, Tuple<S, T...>>
743{
744 static constexpr bool value = is_one_of<F, S, Tuple<T...>>::value;
745};
746
747//======================================================================================//
748// check if trait is satisfied by at least one type in variadic sequence
749//
750template <template <typename> class Test, typename Sequence>
751struct contains_one_of;
752
753template <template <typename> class Test, template <typename...> class Tuple>
754struct contains_one_of<Test, Tuple<>>
755{
756 static constexpr bool value = false;
757 using type = Tuple<>;
758};
759
760template <template <typename> class Test, typename F, template <typename...> class Tuple,
761 typename... T>
762struct contains_one_of<Test, Tuple<F, T...>>
763{
764 static constexpr bool value =
765 Test<F>::value || contains_one_of<Test, Tuple<T...>>::value;
766 using type = conditional_t<Test<F>::value, F,
767 typename contains_one_of<Test, Tuple<T...>>::type>;
768};
769
770} // namespace impl
771
772//======================================================================================//
773///
774/// check if type is in expansion
775///
776template <typename Tp, typename Types>
777using is_one_of = typename impl::is_one_of<Tp, Types>;
778
779///
780/// check if type is in expansion
781///
782template <template <typename> class Predicate, typename Types>
783using contains_one_of = typename impl::contains_one_of<Predicate, Types>;
784
785template <template <typename> class Predicate, typename Types>
786using contains_one_of_t = typename contains_one_of<Predicate, Types>::type;
787
788//======================================================================================//
789
790namespace impl
791{
792template <typename T>
793struct wrapper_index_sequence;
794template <typename T>
795struct nonwrapper_index_sequence;
796
797template <template <typename...> class Tuple, typename... Types>
798struct wrapper_index_sequence<Tuple<Types...>>
799{
800 static constexpr auto size = sizeof...(Types);
801 static constexpr auto value = make_index_sequence<size>{};
802 using type = decltype(make_index_sequence<size>{});
803};
804
805template <template <typename...> class Tuple, typename... Types>
806struct nonwrapper_index_sequence<Tuple<Types...>>
807{
808 static constexpr auto size = sizeof...(Types);
809 static constexpr auto value = type_list<>{};
810 using type = type_list<>;
811};
812} // namespace impl
813
814template <typename Tp>
815struct get_index_sequence
816{
817 static constexpr auto size = 0;
818 static constexpr auto value = type_list<>{};
819 using type = type_list<>;
820};
821
822template <typename Lhs, typename Rhs>
823struct get_index_sequence<std::pair<Lhs, Rhs>>
824{
825 static constexpr auto size = 2;
826 static constexpr auto value = index_sequence<0, 1>{};
827 using type = index_sequence<0, 1>;
828};
829
830template <typename... Types>
831struct get_index_sequence<std::tuple<Types...>>
832{
833 static constexpr auto size = std::tuple_size<std::tuple<Types...>>::value;
834 static constexpr auto value = make_index_sequence<size>{};
835 using type = decltype(make_index_sequence<size>{});
836};
837
838template <template <typename...> class Tuple, typename... Types>
839struct get_index_sequence<Tuple<Types...>>
840{
841 using base_type = conditional_t<concepts::is_variadic<Tuple<Types...>>::value,
842 impl::wrapper_index_sequence<Tuple<Types...>>,
843 impl::nonwrapper_index_sequence<Tuple<Types...>>>;
844 static constexpr auto size = base_type::size;
845 static constexpr auto value = base_type::value;
846 using type = typename base_type::type;
847};
848
849template <typename Tp>
850using get_index_sequence_t = typename get_index_sequence<decay_t<Tp>>::type;
851
852//======================================================================================//
853
854template <typename T, typename U>
855using convert_t = typename impl::convert<T, U>::type;
856
857template <template <typename...> class T, typename... U>
858using convert_each_t = typename impl::convert_each<T, U...>::type;
859
860template <typename T>
861using unwrap_t = typename impl::unwrapper<T>::type;
862
863template <template <typename> class CheckT, bool CheckV,
864 template <typename> class TransformT, typename T, typename U>
865using apply_transform_t =
866 typename impl::apply_transform<CheckT, CheckV, TransformT, T, U>::type;
867
868//======================================================================================//
869
870namespace mpl
871{
872//--------------------------------------------------------------------------------------//
873
874template <typename Tp,
875 typename std::enable_if<(std::is_arithmetic<Tp>::value), int>::type = 0>
876constexpr auto
877get_size(const Tp&, std::tuple<>) -> size_t
878{
879 return 1;
880}
881
882template <typename Tp>
883auto
884get_size(const Tp& _val, std::tuple<>) -> decltype(_val.size(), size_t())
885{
886 return _val.size();
887}
888
889template <typename Tp,
890 typename std::enable_if<(std::is_arithmetic<Tp>::value), int>::type = 0>
891constexpr auto
892get_size(const Tp&, type_list<>) -> size_t
893{
894 return 1;
895}
896
897template <typename Tp>
898auto
899get_size(const Tp& _val, type_list<>) -> decltype(_val.size(), size_t())
900{
901 return _val.size();
902}
903
904template <typename Tp, size_t... Idx>
905constexpr auto
906get_size(const Tp& _val, index_sequence<Idx...>) -> decltype(std::get<0>(_val), size_t())
907{
908 return std::tuple_size<Tp>::value;
909}
910
911template <typename Tp>
912auto
913get_size(const Tp& _val)
914 -> decltype(get_size(_val, get_index_sequence<decay_t<Tp>>::value))
915{
916 return get_size(_val, get_index_sequence<decay_t<Tp>>::value);
917}
918
919template <typename Tp>
920struct get_tuple_size
921{
922 static constexpr size_t value = get_index_sequence<decay_t<Tp>>::size;
923};
924
925//--------------------------------------------------------------------------------------//
926
927template <typename T>
928auto
929resize(T&, ...) -> void
930{}
931
932template <typename T>
933auto
934resize(T& _targ, size_t _n) -> decltype(_targ.resize(_n), void())
935{
936 _targ.resize(_n);
937}
938
939//--------------------------------------------------------------------------------------//
940
941template <typename Tp>
942void
943assign(Tp& _targ, const Tp& _val, ...)
944{
945 _targ = _val;
946}
947
948template <typename Tp, typename Vp, typename ValueType = typename Tp::value_type>
949auto
950assign(Tp& _targ, const Vp& _val, type_list<>) -> decltype(_targ[0], void())
951{
952 auto _n = get_size(_val);
953 resize(_targ, _n);
954 for(decltype(_n) i = 0; i < _n; ++i)
955 {
956 assign(_targ[i], *(_val.begin() + i),
957 get_index_sequence<decay_t<ValueType>>::value);
958 }
959}
960
961template <typename Tp, size_t... Idx>
962auto
963assign(Tp& _targ, const Tp& _val, index_sequence<Idx...>)
964 -> decltype(std::get<0>(_val), void())
965{
966 TIMEMORY_FOLD_EXPRESSION(
967 assign(std::get<Idx>(_targ), std::get<Idx>(_val),
968 get_index_sequence<decay_t<decltype(std::get<Idx>(_targ))>>::value));
969}
970
971template <typename Tp, typename Vp, size_t... Idx,
972 enable_if_t<!std::is_same<Tp, Vp>::value, int> = 0>
973auto
974assign(Tp& _targ, const Vp& _val, index_sequence<Idx...>)
975 -> decltype(std::get<0>(_targ) = *std::begin(_val), void())
976{
977 TIMEMORY_FOLD_EXPRESSION(
978 assign(std::get<Idx>(_targ), *(std::begin(_val) + Idx),
979 get_index_sequence<decay_t<decltype(std::get<Idx>(_targ))>>::value));
980}
981
982template <typename Tp, typename Vp>
983void
984assign(Tp& _targ, const Vp& _val)
985{
986 assign(_targ, _val, get_index_sequence<decay_t<Tp>>::value);
987}
988
989//--------------------------------------------------------------------------------------//
990
991template <typename Tuple, typename T>
992struct push_back;
993
994template <template <typename...> class Tuple, typename... Types, typename T>
995struct push_back<Tuple<Types...>, T>
996{
997 using type = Tuple<Types..., T>;
998};
999
1000template <template <typename, typename> class Hybrid, template <typename...> class Lhs,
1001 typename... LhsTypes, template <typename...> class Rhs, typename... RhsTypes,
1002 typename T>
1003struct push_back<Hybrid<Lhs<LhsTypes...>, Rhs<RhsTypes...>>, T>
1004{
1005 using type = Hybrid<Lhs<LhsTypes..., T>, Rhs<RhsTypes...>>;
1006};
1007
1008//--------------------------------------------------------------------------------------//
1009
1010template <typename... T>
1011struct union_index_of;
1012
1013template <typename T, template <typename...> class TupleT, typename... Types>
1014struct union_index_of<T, TupleT<Types...>>
1015{
1016 template <typename U = T>
1017 static constexpr auto value(
1018 int, enable_if_t<is_one_of<U, TupleT<Types...>>::value, int> = 0)
1019 {
1020 return index_of<T, TupleT<Types...>>::value;
1021 }
1022
1023 template <typename U = T>
1024 static constexpr auto value(
1025 long, enable_if_t<is_one_of<U*, TupleT<Types...>>::value, int> = 0)
1026 {
1027 return index_of<T*, TupleT<Types...>>::value;
1028 }
1029};
1030
1031template <typename T, template <typename...> class TupleT, typename... Types>
1032struct union_index_of<T*, TupleT<Types...>>
1033{
1034 template <typename U = T>
1035 static constexpr auto value(
1036 long, enable_if_t<is_one_of<U, TupleT<Types...>>::value, int> = 0)
1037 {
1038 return index_of<T, TupleT<Types...>>::value;
1039 }
1040
1041 template <typename U = T>
1042 static constexpr auto value(
1043 int, enable_if_t<is_one_of<U*, TupleT<Types...>>::value, int> = 0)
1044 {
1045 return index_of<T*, TupleT<Types...>>::value;
1046 }
1047};
1048
1049template <typename... T>
1050struct union_index_sequence;
1051
1052template <template <typename...> class LhsT, typename... Lhs,
1053 template <typename...> class RhsT, typename... Rhs>
1054struct union_index_sequence<LhsT<Lhs...>, RhsT<Rhs...>>
1055{
1056 using type =
1057 index_sequence<union_index_of<decay_t<Lhs>, RhsT<decay_t<Rhs>...>>::value(0)...>;
1058};
1059
1060template <typename... T>
1061using union_index_sequence_t = typename union_index_sequence<T...>::type;
1062
1063namespace impl
1064{
1065template <typename Tp, size_t... Idx>
1066TIMEMORY_INLINE decltype(auto)
1067get_reference_tuple(Tp&& _tuple, index_sequence<Idx...>)
1068{
1069 return std::tie(std::get<Idx>(_tuple)...);
1070}
1071} // namespace impl
1072
1073template <typename Rp, typename Tp>
1074TIMEMORY_INLINE decltype(auto)
1075get_reference_tuple(Tp&& _tuple)
1076{
1077 // static_assert(concepts::is_variadic<Tp>::value, "Requires variadic type");
1078 using sequence_type = union_index_sequence_t<Rp, decay_t<Tp>>;
1079 return impl::get_reference_tuple(std::forward<Tp>(_tuple), sequence_type{});
1080}
1081
1082//--------------------------------------------------------------------------------------//
1083
1084} // namespace mpl
1085
1086template <typename Tuple, typename T>
1087using push_back_t = typename mpl::push_back<Tuple, T>::type;
1088
1089} // namespace tim
Definition: kokkosp.cpp:39
typename component_bundle
Definition: types.hpp:221