File indexing completed on 2025-01-18 10:06:09
0001 #ifndef PODIO_UTILITIES_TYPEHELPERS_H
0002 #define PODIO_UTILITIES_TYPEHELPERS_H
0003
0004 #include <map>
0005 #include <string>
0006 #include <tuple>
0007 #include <type_traits>
0008 #include <unordered_map>
0009 #include <vector>
0010
0011 namespace podio {
0012 #if __has_include("experimental/type_traits.h")
0013 #include <experimental/type_traits>
0014 namespace det {
0015 using namespace std::experimental;
0016 }
0017 #else
0018
0019 namespace det {
0020 namespace detail {
0021 template <typename DefT, typename AlwaysVoidT, template <typename...> typename Op, typename... Args>
0022 struct detector {
0023 using value_t = std::false_type;
0024 using type = DefT;
0025 };
0026
0027 template <typename DefT, template <typename...> typename Op, typename... Args>
0028 struct detector<DefT, std::void_t<Op<Args...>>, Op, Args...> {
0029 using value_t = std::true_type;
0030 using type = Op<Args...>;
0031 };
0032 }
0033
0034 struct nonesuch {
0035 ~nonesuch() = delete;
0036 nonesuch(const nonesuch&) = delete;
0037 void operator=(const nonesuch&) = delete;
0038 };
0039
0040 template <template <typename...> typename Op, typename... Args>
0041 using is_detected = typename detail::detector<nonesuch, void, Op, Args...>::value_t;
0042
0043 template <template <typename...> typename Op, typename... Args>
0044 static constexpr bool is_detected_v = is_detected<Op, Args...>::value;
0045
0046 template <typename DefT, template <typename...> typename Op, typename... Args>
0047 using detected_or = detail::detector<DefT, void, Op, Args...>;
0048 }
0049 #endif
0050
0051 namespace detail {
0052
0053
0054
0055 template <typename T, typename>
0056 struct TypeInTupleHelper : std::false_type {};
0057
0058 template <typename T, typename... Ts>
0059 struct TypeInTupleHelper<T, std::tuple<Ts...>> : std::bool_constant<(std::is_same_v<T, Ts> || ...)> {};
0060
0061
0062
0063 template <typename T, typename Tuple>
0064 static constexpr bool isInTuple = TypeInTupleHelper<T, Tuple>::value;
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 template <template <typename...> typename Template, typename T>
0077 struct ToTupleOfTemplateHelper;
0078
0079 template <template <typename...> typename Template, typename... Ts>
0080 struct ToTupleOfTemplateHelper<Template, std::tuple<Ts...>> {
0081 using type = std::tuple<Template<Ts>...>;
0082 };
0083
0084
0085 template <typename Tuple>
0086 using TupleOfVector = typename ToTupleOfTemplateHelper<std::vector, Tuple>::type;
0087
0088
0089
0090
0091 template <typename... Tuples>
0092 using TupleCatType = decltype(std::tuple_cat(std::declval<Tuples>()...));
0093
0094
0095
0096 template <typename T, typename Tuple>
0097 static constexpr bool isAnyOrVectorOf = isInTuple<T, TupleCatType<Tuple, TupleOfVector<Tuple>>>;
0098
0099
0100
0101
0102 template <typename T>
0103 struct GetVectorTypeHelper {
0104 using type = T;
0105 };
0106
0107 template <typename T>
0108 struct GetVectorTypeHelper<std::vector<T>> {
0109 using type = T;
0110 };
0111
0112 template <typename T>
0113 using GetVectorType = typename GetVectorTypeHelper<T>::type;
0114
0115
0116 template <typename T>
0117 struct IsVectorHelper : std::false_type {};
0118
0119 template <typename T>
0120 struct IsVectorHelper<std::vector<T>> : std::true_type {};
0121
0122
0123 template <typename T>
0124 static constexpr bool isVector = IsVectorHelper<T>::value;
0125
0126
0127 template <typename T>
0128 struct IsMapHelper : std::false_type {};
0129
0130 template <typename K, typename V>
0131 struct IsMapHelper<std::map<K, V>> : std::true_type {};
0132
0133 template <typename K, typename V>
0134 struct IsMapHelper<std::unordered_map<K, V>> : std::true_type {};
0135
0136
0137
0138 template <typename T>
0139 static constexpr bool isMap = IsMapHelper<T>::value;
0140
0141
0142
0143
0144
0145 template <typename T, typename IsMap = std::bool_constant<isMap<T>>,
0146 typename IsVector = std::bool_constant<isVector<T> && (std::tuple_size<typename T::value_type>() == 2)>>
0147 struct MapLikeTypeHelper {};
0148
0149
0150 template <typename T>
0151 struct MapLikeTypeHelper<T, std::bool_constant<true>, std::bool_constant<false>> {
0152 using key_type = typename T::key_type;
0153 using mapped_type = typename T::mapped_type;
0154 };
0155
0156
0157 template <typename T>
0158 struct MapLikeTypeHelper<T, std::bool_constant<false>, std::bool_constant<true>> {
0159 using key_type = typename std::tuple_element<0, typename T::value_type>::type;
0160 using mapped_type = typename std::tuple_element<1, typename T::value_type>::type;
0161 };
0162
0163
0164 template <typename T>
0165 using GetKeyType = typename MapLikeTypeHelper<T>::key_type;
0166
0167 template <typename T>
0168 using GetMappedType = typename MapLikeTypeHelper<T>::mapped_type;
0169
0170
0171
0172
0173 template <typename T>
0174 using hasMutable_t = typename T::mutable_type;
0175
0176
0177
0178 template <typename T>
0179 using hasObject_t = typename T::object_type;
0180
0181
0182
0183
0184
0185
0186
0187
0188 template <typename T>
0189 constexpr static bool isPodioType = det::is_detected_v<hasObject_t, T> || det::is_detected_v<hasMutable_t, T>;
0190
0191
0192
0193
0194
0195
0196 template <typename T>
0197 using GetDefaultHandleType = typename det::detected_or<T, hasObject_t, T>::type;
0198
0199
0200
0201
0202
0203
0204 template <typename T>
0205 using GetMutableHandleType = typename det::detected_or<T, hasMutable_t, T>::type;
0206
0207
0208
0209 template <typename Tuple>
0210 using TupleOfMutableTypes = typename ToTupleOfTemplateHelper<GetMutableHandleType, Tuple>::type;
0211
0212 }
0213
0214
0215 class CollectionBase;
0216
0217
0218 template <typename T>
0219 static constexpr bool isCollection = std::is_base_of_v<CollectionBase, T>;
0220
0221 }
0222
0223 #endif