File indexing completed on 2025-07-01 08:45:49
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 template <template <typename...> typename Op, typename... Args>
0050 using detected_t = typename detail::detector<nonesuch, void, Op, Args...>::type;
0051 }
0052 #endif
0053
0054 namespace detail {
0055
0056
0057
0058 template <typename T, typename>
0059 struct TypeInTupleHelper : std::false_type {};
0060
0061 template <typename T, typename... Ts>
0062 struct TypeInTupleHelper<T, std::tuple<Ts...>> : std::bool_constant<(std::is_same_v<T, Ts> || ...)> {};
0063
0064
0065
0066 template <typename T, typename Tuple>
0067 static constexpr bool isInTuple = TypeInTupleHelper<T, Tuple>::value;
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079 template <template <typename...> typename Template, typename T>
0080 struct ToTupleOfTemplateHelper;
0081
0082 template <template <typename...> typename Template, typename... Ts>
0083 struct ToTupleOfTemplateHelper<Template, std::tuple<Ts...>> {
0084 using type = std::tuple<Template<Ts>...>;
0085 };
0086
0087
0088 template <typename Tuple>
0089 using TupleOfVector = typename ToTupleOfTemplateHelper<std::vector, Tuple>::type;
0090
0091
0092
0093
0094 template <typename... Tuples>
0095 using TupleCatType = decltype(std::tuple_cat(std::declval<Tuples>()...));
0096
0097
0098
0099 template <typename T, typename Tuple>
0100 static constexpr bool isAnyOrVectorOf = isInTuple<T, TupleCatType<Tuple, TupleOfVector<Tuple>>>;
0101
0102
0103
0104
0105 template <typename T>
0106 struct GetVectorTypeHelper {
0107 using type = T;
0108 };
0109
0110 template <typename T>
0111 struct GetVectorTypeHelper<std::vector<T>> {
0112 using type = T;
0113 };
0114
0115 template <typename T>
0116 using GetVectorType = typename GetVectorTypeHelper<T>::type;
0117
0118
0119 template <typename T>
0120 struct IsVectorHelper : std::false_type {};
0121
0122 template <typename T>
0123 struct IsVectorHelper<std::vector<T>> : std::true_type {};
0124
0125
0126 template <typename T>
0127 static constexpr bool isVector = IsVectorHelper<T>::value;
0128
0129
0130 template <typename T>
0131 struct IsMapHelper : std::false_type {};
0132
0133 template <typename K, typename V>
0134 struct IsMapHelper<std::map<K, V>> : std::true_type {};
0135
0136 template <typename K, typename V>
0137 struct IsMapHelper<std::unordered_map<K, V>> : std::true_type {};
0138
0139
0140
0141 template <typename T>
0142 static constexpr bool isMap = IsMapHelper<T>::value;
0143
0144
0145
0146
0147
0148 template <typename T, typename IsMap = std::bool_constant<isMap<T>>,
0149 typename IsVector = std::bool_constant<isVector<T> && (std::tuple_size<typename T::value_type>() == 2)>>
0150 struct MapLikeTypeHelper {};
0151
0152
0153 template <typename T>
0154 struct MapLikeTypeHelper<T, std::bool_constant<true>, std::bool_constant<false>> {
0155 using key_type = typename T::key_type;
0156 using mapped_type = typename T::mapped_type;
0157 };
0158
0159
0160 template <typename T>
0161 struct MapLikeTypeHelper<T, std::bool_constant<false>, std::bool_constant<true>> {
0162 using key_type = typename std::tuple_element<0, typename T::value_type>::type;
0163 using mapped_type = typename std::tuple_element<1, typename T::value_type>::type;
0164 };
0165
0166
0167 template <typename T>
0168 using GetKeyType = typename MapLikeTypeHelper<T>::key_type;
0169
0170 template <typename T>
0171 using GetMappedType = typename MapLikeTypeHelper<T>::mapped_type;
0172
0173
0174
0175
0176 template <typename T>
0177 using hasMutable_t = typename T::mutable_type;
0178
0179
0180
0181 template <typename T>
0182 using hasObject_t = typename T::object_type;
0183
0184
0185 template <typename T>
0186 using hasCollection_t = typename T::collection_type;
0187
0188
0189
0190 template <typename T>
0191 constexpr static bool isMutableHandleType = det::is_detected_v<hasObject_t, std::remove_reference_t<T>>;
0192
0193
0194
0195 template <typename T>
0196 constexpr static bool isDefaultHandleType = det::is_detected_v<hasMutable_t, std::remove_reference_t<T>>;
0197
0198
0199
0200
0201
0202
0203
0204
0205 template <typename T>
0206 constexpr static bool isPodioType = isDefaultHandleType<T> || isMutableHandleType<T>;
0207
0208
0209
0210
0211
0212
0213 template <typename T>
0214 using GetDefaultHandleType =
0215 typename det::detected_or<std::remove_reference_t<T>, hasObject_t, std::remove_reference_t<T>>::type;
0216
0217
0218
0219
0220
0221
0222 template <typename T>
0223 using GetMutableHandleType =
0224 typename det::detected_or<std::remove_reference_t<T>, hasMutable_t, std::remove_reference_t<T>>::type;
0225
0226
0227
0228 template <typename T>
0229 using GetCollectionType = det::detected_t<hasCollection_t, std::remove_reference_t<T>>;
0230
0231
0232
0233 template <typename Tuple>
0234 using TupleOfMutableTypes = typename ToTupleOfTemplateHelper<GetMutableHandleType, Tuple>::type;
0235
0236
0237 template <typename T>
0238 using hasInterface_t = typename T::interfaced_types;
0239
0240
0241
0242
0243
0244 template <typename T>
0245 constexpr static bool isInterfaceType = det::is_detected_v<hasInterface_t, std::remove_reference_t<T>>;
0246
0247
0248
0249 template <typename T, typename U, typename isInterface = std::bool_constant<isInterfaceType<T>>>
0250 struct InterfaceInitializerHelper {};
0251
0252
0253
0254 template <typename T, typename U>
0255 struct InterfaceInitializerHelper<T, U, std::bool_constant<true>>
0256 : std::bool_constant<T::template isInitializableFrom<U>> {};
0257
0258
0259 template <typename T, typename U>
0260 struct InterfaceInitializerHelper<T, U, std::bool_constant<false>> : std::false_type {};
0261
0262
0263
0264 template <typename T, typename U>
0265 constexpr static bool isInterfaceInitializableFrom = InterfaceInitializerHelper<T, U>::value;
0266
0267 }
0268
0269
0270 class CollectionBase;
0271
0272
0273 template <typename T>
0274 static constexpr bool isCollection = std::is_base_of_v<CollectionBase, T>;
0275
0276 }
0277
0278 #endif