54#if defined(TIMEMORY_USE_DEPRECATED)
56template <
typename TupleT,
typename ListT>
59template <typename TupleT, typename ListT>
60class [[deprecated("Use auto_bundle<T..., L*...>
")]] auto_hybrid;
64//======================================================================================//
65// type-traits for customization
70using default_record_statistics_type = TIMEMORY_DEFAULT_STATISTICS_TYPE;
72template <typename TraitT>
78template <template <typename...> class TraitT, typename... CommonT>
82 TIMEMORY_DEFAULT_OBJECT(apply)
84 template <typename... Types, typename... Args>
85 static inline void set(Args&&... args)
87 TIMEMORY_FOLD_EXPRESSION(
88 TraitT<Types, CommonT...>::set(std::forward<Args>(args)...));
91 template <typename... Types, typename... Args>
92 static inline auto get(Args&&... args)
94 return std::make_tuple(
95 TraitT<Types, CommonT...>::get(std::forward<Args>(args)...)...);
98 template <typename... Types>
99 inline bool operator()(type_list<Types...>)
102 TIMEMORY_FOLD_EXPRESSION(_ret = _ret && TraitT<Types>::get());
108struct base_has_accum;
119template <typename T, bool>
120struct component_value_type;
126using runtime_configurable = concepts::is_runtime_configurable<T>;
128template <typename T = void>
129struct supports_runtime_enabled;
131template <typename T = void>
132struct default_runtime_enabled;
134template <typename T = void>
135struct runtime_enabled;
141struct array_serialization;
144struct requires_prefix;
147struct custom_label_printing;
150struct custom_unit_printing;
153struct start_priority;
162struct is_timing_category;
165struct is_memory_category;
168struct uses_timing_units;
171struct uses_memory_units;
174struct uses_percent_units;
182template <typename T, typename Tag = void>
183struct api_components;
186struct component_apis;
192struct is_user_bundle;
194template <typename T, typename Tuple>
198struct supports_custom_record;
201struct iterable_measurement;
204struct secondary_data;
207struct thread_scope_only;
210struct custom_serialization;
213struct record_statistics;
219struct permissive_statistics;
233template <typename Api = TIMEMORY_API>
234struct api_input_archive;
236template <typename Api = TIMEMORY_API>
237struct api_output_archive;
239template <typename T, typename Api = TIMEMORY_API>
242template <typename T, typename Api = TIMEMORY_API>
243struct output_archive;
246struct pretty_archive;
249struct archive_extension;
261struct report_metric_name;
273struct report_statistics;
282struct supports_flamegraph;
285struct derivation_types;
287template <int OpT, typename T>
293template <typename T, typename V = trait::data<T>>
294struct generates_output;
306struct timeline_storage;
308template <typename T, typename V = trait::data<T>, typename A = trait::uses_storage<T>>
309struct uses_value_storage;
311template <typename ApiT>
312struct perfetto_category;
314//--------------------------------------------------------------------------------------//
318//--------------------------------------------------------------------------------------//
321using input_archive_t = typename input_archive<T, TIMEMORY_API>::type;
324using output_archive_t = typename output_archive<T, TIMEMORY_API>::type;
326//--------------------------------------------------------------------------------------//
354struct is_available : TIMEMORY_DEFAULT_AVAILABLE
358struct is_available<T*> : is_available<std::remove_pointer_t<T>>
362using is_available_t = typename is_available<T>::type;
366//======================================================================================//
367// generic helpers that can/should be inherited from
405template <typename T, bool WithThreads = true>
406struct instance_tracker;
430template <typename CompT, typename T = typename trait::statistics<CompT>::type>
431struct record_statistics;
437template <typename Archive, typename Api = TIMEMORY_API>
446template <typename Archive, typename Api = TIMEMORY_API>
447struct output_archive;
449//--------------------------------------------------------------------------------------//
453//--------------------------------------------------------------------------------------//
456using input_archive_t = input_archive<trait::input_archive_t<T>, TIMEMORY_API>;
459using output_archive_t = output_archive<trait::output_archive_t<T>, TIMEMORY_API>;
461//--------------------------------------------------------------------------------------//
466//--------------------------------------------------------------------------------------//
470//--------------------------------------------------------------------------------------//
472template <typename... Types>
475 using type = std::tuple<Types...>;
478//--------------------------------------------------------------------------------------//
483 using type = std::tuple<>;
486//--------------------------------------------------------------------------------------//
488template <typename... Ts>
489struct tuple_concat<std::tuple<Ts...>>
491 using type = std::tuple<Ts...>;
494//--------------------------------------------------------------------------------------//
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...>
501//--------------------------------------------------------------------------------------//
503// type_list concatenation
505//--------------------------------------------------------------------------------------//
507template <typename... Types>
510 using type = type_list<Types...>;
513//--------------------------------------------------------------------------------------//
518 using type = type_list<>;
521//--------------------------------------------------------------------------------------//
523template <typename... Ts>
524struct type_concat<type_list<Ts...>>
526 using type = type_list<Ts...>;
529//--------------------------------------------------------------------------------------//
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...>
536//--------------------------------------------------------------------------------------//
540template <typename Tp, typename Type>
543template <typename Tp, template <typename...> class Tuple, typename... Types>
544struct index_of<Tp, Tuple<Tp, Types...>>
546 static constexpr size_t value = 0;
549template <typename Tp, typename Head, template <typename...> class Tuple,
551struct index_of<Tp, Tuple<Head, Tail...>>
553 static constexpr size_t value = 1 + index_of<Tp, Tuple<Tail...>>::value;
556//--------------------------------------------------------------------------------------//
560//======================================================================================//
562template <typename... Ts>
563using tuple_concat_t = typename impl::tuple_concat<Ts...>::type;
565template <typename... Ts>
566using type_concat_t = typename impl::type_concat<Ts...>::type;
569using remove_pointer_t = typename std::remove_pointer<U>::type;
572using add_pointer_t = conditional_t<(std::is_pointer<U>::value), U, U*>;
574template <typename Tp, typename Type>
575using index_of = impl::index_of<Tp, Type>;
577//======================================================================================//
581//--------------------------------------------------------------------------------------//
589//--------------------------------------------------------------------------------------//
591template <template <typename...> class Tuple, typename... T>
592struct unwrapper<Tuple<T...>>
594 using type = Tuple<T...>;
597//--------------------------------------------------------------------------------------//
599template <template <typename...> class Tuple, typename... T>
600struct unwrapper<Tuple<Tuple<T...>>>
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...>>>;
607//--------------------------------------------------------------------------------------//
609template <typename In, typename Out>
614 using input_type = In;
615 using output_type = Out;
617 static output_type apply(const input_type& _in)
619 return static_cast<output_type>(_in);
623//--------------------------------------------------------------------------------------//
625template <template <typename...> class InTuple, typename... In,
626 template <typename...> class OutTuple, typename... Out>
627struct convert<InTuple<In...>, OutTuple<Out...>>
629 using type = OutTuple<Out..., In...>;
631 using input_type = InTuple<In...>;
632 using output_type = OutTuple<Out...>;
634 static output_type apply(const input_type& _in)
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)));
644//--------------------------------------------------------------------------------------//
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>>
652//--------------------------------------------------------------------------------------//
654template <template <typename...> class InTuple, typename... T>
657template <template <typename...> class OutTuple, template <typename...> class InTuple,
659struct convert_each<OutTuple, InTuple<In...>>
661 using type = std::tuple<OutTuple<In>...>;
664//--------------------------------------------------------------------------------------//
666#if defined(TIMEMORY_USE_DEPRECATED)
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...>>>
675 using type = auto_hybrid<LhsInT<LhsIn...>, RhsInT<RhsIn...>>;
678//--------------------------------------------------------------------------------------//
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...>>>
687 using type = component_hybrid<LhsInT<LhsIn...>, RhsInT<RhsIn...>>;
692//--------------------------------------------------------------------------------------//
694template <template <typename> class CheckT, bool CheckV,
695 template <typename> class TransformT, typename... T>
696struct apply_transform;
698//--------------------------------------------------------------------------------------//
700/*template <typename In, typename Out>
701struct apply_transform<identity, true, identity, In, Out>
706//--------------------------------------------------------------------------------------//
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...>>
712 using type = type_list<Out..., conditional_t<CheckT<In>::value == CheckV,
713 typename TransformT<In>::type, In>...>;
716//--------------------------------------------------------------------------------------//
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...>,
722: apply_transform<CheckT, CheckV, TransformT, type_list<In...>, type_list<ApiT>>
725//======================================================================================//
726// check if type is in expansion
728template <typename... Tp>
731 static constexpr bool value = false;
734template <typename F, typename S, template <typename...> class Tuple, typename... T>
735struct is_one_of<F, S, Tuple<T...>>
737 static constexpr bool value =
738 std::is_same<F, S>::value || is_one_of<F, Tuple<T...>>::value;
741template <typename F, typename S, template <typename...> class Tuple, typename... T>
742struct is_one_of<F, Tuple<S, T...>>
744 static constexpr bool value = is_one_of<F, S, Tuple<T...>>::value;
747//======================================================================================//
748// check if trait is satisfied by at least one type in variadic sequence
750template <template <typename> class Test, typename Sequence>
751struct contains_one_of;
753template <template <typename> class Test, template <typename...> class Tuple>
754struct contains_one_of<Test, Tuple<>>
756 static constexpr bool value = false;
757 using type = Tuple<>;
760template <template <typename> class Test, typename F, template <typename...> class Tuple,
762struct contains_one_of<Test, Tuple<F, T...>>
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>;
772//======================================================================================//
776template <typename Tp, typename Types>
777using is_one_of = typename impl::is_one_of<Tp, Types>;
782template <template <typename> class Predicate, typename Types>
783using contains_one_of = typename impl::contains_one_of<Predicate, Types>;
785template <template <typename> class Predicate, typename Types>
786using contains_one_of_t = typename contains_one_of<Predicate, Types>::type;
788//======================================================================================//
793struct wrapper_index_sequence;
795struct nonwrapper_index_sequence;
797template <template <typename...> class Tuple, typename... Types>
798struct wrapper_index_sequence<Tuple<Types...>>
800 static constexpr auto size = sizeof...(Types);
801 static constexpr auto value = make_index_sequence<size>{};
802 using type = decltype(make_index_sequence<size>{});
805template <template <typename...> class Tuple, typename... Types>
806struct nonwrapper_index_sequence<Tuple<Types...>>
808 static constexpr auto size = sizeof...(Types);
809 static constexpr auto value = type_list<>{};
810 using type = type_list<>;
814template <typename Tp>
815struct get_index_sequence
817 static constexpr auto size = 0;
818 static constexpr auto value = type_list<>{};
819 using type = type_list<>;
822template <typename Lhs, typename Rhs>
823struct get_index_sequence<std::pair<Lhs, Rhs>>
825 static constexpr auto size = 2;
826 static constexpr auto value = index_sequence<0, 1>{};
827 using type = index_sequence<0, 1>;
830template <typename... Types>
831struct get_index_sequence<std::tuple<Types...>>
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>{});
838template <template <typename...> class Tuple, typename... Types>
839struct get_index_sequence<Tuple<Types...>>
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;
849template <typename Tp>
850using get_index_sequence_t = typename get_index_sequence<decay_t<Tp>>::type;
852//======================================================================================//
854template <typename T, typename U>
855using convert_t = typename impl::convert<T, U>::type;
857template <template <typename...> class T, typename... U>
858using convert_each_t = typename impl::convert_each<T, U...>::type;
861using unwrap_t = typename impl::unwrapper<T>::type;
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;
868//======================================================================================//
872//--------------------------------------------------------------------------------------//
874template <typename Tp,
875 typename std::enable_if<(std::is_arithmetic<Tp>::value), int>::type = 0>
877get_size(const Tp&, std::tuple<>) -> size_t
882template <typename Tp>
884get_size(const Tp& _val, std::tuple<>) -> decltype(_val.size(), size_t())
889template <typename Tp,
890 typename std::enable_if<(std::is_arithmetic<Tp>::value), int>::type = 0>
892get_size(const Tp&, type_list<>) -> size_t
897template <typename Tp>
899get_size(const Tp& _val, type_list<>) -> decltype(_val.size(), size_t())
904template <typename Tp, size_t... Idx>
906get_size(const Tp& _val, index_sequence<Idx...>) -> decltype(std::get<0>(_val), size_t())
908 return std::tuple_size<Tp>::value;
911template <typename Tp>
913get_size(const Tp& _val)
914 -> decltype(get_size(_val, get_index_sequence<decay_t<Tp>>::value))
916 return get_size(_val, get_index_sequence<decay_t<Tp>>::value);
919template <typename Tp>
922 static constexpr size_t value = get_index_sequence<decay_t<Tp>>::size;
925//--------------------------------------------------------------------------------------//
929resize(T&, ...) -> void
934resize(T& _targ, size_t _n) -> decltype(_targ.resize(_n), void())
939//--------------------------------------------------------------------------------------//
941template <typename Tp>
943assign(Tp& _targ, const Tp& _val, ...)
948template <typename Tp, typename Vp, typename ValueType = typename Tp::value_type>
950assign(Tp& _targ, const Vp& _val, type_list<>) -> decltype(_targ[0], void())
952 auto _n = get_size(_val);
954 for(decltype(_n) i = 0; i < _n; ++i)
956 assign(_targ[i], *(_val.begin() + i),
957 get_index_sequence<decay_t<ValueType>>::value);
961template <typename Tp, size_t... Idx>
963assign(Tp& _targ, const Tp& _val, index_sequence<Idx...>)
964 -> decltype(std::get<0>(_val), void())
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));
971template <typename Tp, typename Vp, size_t... Idx,
972 enable_if_t<!std::is_same<Tp, Vp>::value, int> = 0>
974assign(Tp& _targ, const Vp& _val, index_sequence<Idx...>)
975 -> decltype(std::get<0>(_targ) = *std::begin(_val), void())
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));
982template <typename Tp, typename Vp>
984assign(Tp& _targ, const Vp& _val)
986 assign(_targ, _val, get_index_sequence<decay_t<Tp>>::value);
989//--------------------------------------------------------------------------------------//
991template <typename Tuple, typename T>
994template <template <typename...> class Tuple, typename... Types, typename T>
995struct push_back<Tuple<Types...>, T>
997 using type = Tuple<Types..., T>;
1000template <template <typename, typename> class Hybrid, template <typename...> class Lhs,
1001 typename... LhsTypes, template <typename...> class Rhs, typename... RhsTypes,
1003struct push_back<Hybrid<Lhs<LhsTypes...>, Rhs<RhsTypes...>>, T>
1005 using type = Hybrid<Lhs<LhsTypes..., T>, Rhs<RhsTypes...>>;
1008//--------------------------------------------------------------------------------------//
1010template <typename... T>
1011struct union_index_of;
1013template <typename T, template <typename...> class TupleT, typename... Types>
1014struct union_index_of<T, TupleT<Types...>>
1016 template <typename U = T>
1017 static constexpr auto value(
1018 int, enable_if_t<is_one_of<U, TupleT<Types...>>::value, int> = 0)
1020 return index_of<T, TupleT<Types...>>::value;
1023 template <typename U = T>
1024 static constexpr auto value(
1025 long, enable_if_t<is_one_of<U*, TupleT<Types...>>::value, int> = 0)
1027 return index_of<T*, TupleT<Types...>>::value;
1031template <typename T, template <typename...> class TupleT, typename... Types>
1032struct union_index_of<T*, TupleT<Types...>>
1034 template <typename U = T>
1035 static constexpr auto value(
1036 long, enable_if_t<is_one_of<U, TupleT<Types...>>::value, int> = 0)
1038 return index_of<T, TupleT<Types...>>::value;
1041 template <typename U = T>
1042 static constexpr auto value(
1043 int, enable_if_t<is_one_of<U*, TupleT<Types...>>::value, int> = 0)
1045 return index_of<T*, TupleT<Types...>>::value;
1049template <typename... T>
1050struct union_index_sequence;
1052template <template <typename...> class LhsT, typename... Lhs,
1053 template <typename...> class RhsT, typename... Rhs>
1054struct union_index_sequence<LhsT<Lhs...>, RhsT<Rhs...>>
1057 index_sequence<union_index_of<decay_t<Lhs>, RhsT<decay_t<Rhs>...>>::value(0)...>;
1060template <typename... T>
1061using union_index_sequence_t = typename union_index_sequence<T...>::type;
1065template <typename Tp, size_t... Idx>
1066TIMEMORY_INLINE decltype(auto)
1067get_reference_tuple(Tp&& _tuple, index_sequence<Idx...>)
1069 return std::tie(std::get<Idx>(_tuple)...);
1073template <typename Rp, typename Tp>
1074TIMEMORY_INLINE decltype(auto)
1075get_reference_tuple(Tp&& _tuple)
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{});
1082//--------------------------------------------------------------------------------------//
1086template <typename Tuple, typename T>
1087using push_back_t = typename mpl::push_back<Tuple, T>::type;
typename component_bundle