File indexing completed on 2025-09-15 09:06:26
0001 #ifndef PODIO_UTILITIES_TYPEHELPERS_H
0002 #define PODIO_UTILITIES_TYPEHELPERS_H
0003
0004 #include <concepts>
0005 #include <iterator>
0006 #include <map>
0007 #include <ranges>
0008 #include <tuple>
0009 #include <type_traits>
0010 #include <unordered_map>
0011 #include <vector>
0012
0013 namespace podio {
0014
0015 namespace det {
0016 namespace detail {
0017 template <typename DefT, typename AlwaysVoidT, template <typename...> typename Op, typename... Args>
0018 struct detector {
0019 using value_t = std::false_type;
0020 using type = DefT;
0021 };
0022
0023 template <typename DefT, template <typename...> typename Op, typename... Args>
0024 struct detector<DefT, std::void_t<Op<Args...>>, Op, Args...> {
0025 using value_t = std::true_type;
0026 using type = Op<Args...>;
0027 };
0028 }
0029
0030 struct nonesuch {
0031 ~nonesuch() = delete;
0032 nonesuch(const nonesuch&) = delete;
0033 void operator=(const nonesuch&) = delete;
0034 };
0035
0036 template <typename DefT, template <typename...> typename Op, typename... Args>
0037 using detected_or = detail::detector<DefT, void, Op, Args...>;
0038
0039 template <template <typename...> typename Op, typename... Args>
0040 constexpr bool is_detected_v = requires { typename Op<Args...>; };
0041
0042 }
0043
0044 namespace detail {
0045
0046
0047
0048 template <typename T>
0049 inline constexpr bool always_false = false;
0050
0051
0052
0053 template <typename T, typename>
0054 struct TypeInTupleHelper : std::false_type {};
0055
0056 template <typename T, typename... Ts>
0057 struct TypeInTupleHelper<T, std::tuple<Ts...>> : std::disjunction<std::is_same<T, Ts>...> {};
0058
0059
0060
0061 template <typename T, typename Tuple>
0062 static constexpr bool isInTuple = TypeInTupleHelper<T, Tuple>::value;
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074 template <template <typename...> typename Template, typename T>
0075 struct ToTupleOfTemplateHelper;
0076
0077 template <template <typename...> typename Template, typename... Ts>
0078 struct ToTupleOfTemplateHelper<Template, std::tuple<Ts...>> {
0079 using type = std::tuple<Template<Ts>...>;
0080 };
0081
0082
0083 template <typename Tuple>
0084 using TupleOfVector = typename ToTupleOfTemplateHelper<std::vector, Tuple>::type;
0085
0086
0087
0088
0089 template <typename... Tuples>
0090 using TupleCatType = decltype(std::tuple_cat(std::declval<Tuples>()...));
0091
0092
0093
0094 template <typename T, typename Tuple>
0095 static constexpr bool isAnyOrVectorOf = isInTuple<T, TupleCatType<Tuple, TupleOfVector<Tuple>>>;
0096
0097
0098
0099
0100 template <typename T>
0101 struct GetVectorTypeHelper {
0102 using type = T;
0103 };
0104
0105 template <typename T>
0106 struct GetVectorTypeHelper<std::vector<T>> {
0107 using type = T;
0108 };
0109
0110 template <typename T>
0111 using GetVectorType = typename GetVectorTypeHelper<T>::type;
0112
0113
0114 template <typename T>
0115 struct IsVectorHelper : std::false_type {};
0116
0117 template <typename T>
0118 struct IsVectorHelper<std::vector<T>> : std::true_type {};
0119
0120
0121 template <typename T>
0122 static constexpr bool isVector = IsVectorHelper<T>::value;
0123
0124
0125 template <typename T>
0126 struct IsMapHelper : std::false_type {};
0127
0128 template <typename K, typename V>
0129 struct IsMapHelper<std::map<K, V>> : std::true_type {};
0130
0131 template <typename K, typename V>
0132 struct IsMapHelper<std::unordered_map<K, V>> : std::true_type {};
0133
0134
0135
0136 template <typename T>
0137 static constexpr bool isMap = IsMapHelper<T>::value;
0138
0139
0140
0141
0142
0143 template <typename T, typename IsMap = std::bool_constant<isMap<T>>,
0144 typename IsVector = std::bool_constant<isVector<T> && (std::tuple_size<typename T::value_type>() == 2)>>
0145 struct MapLikeTypeHelper {};
0146
0147
0148 template <typename T>
0149 struct MapLikeTypeHelper<T, std::bool_constant<true>, std::bool_constant<false>> {
0150 using key_type = typename T::key_type;
0151 using mapped_type = typename T::mapped_type;
0152 };
0153
0154
0155 template <typename T>
0156 struct MapLikeTypeHelper<T, std::bool_constant<false>, std::bool_constant<true>> {
0157 using key_type = typename std::tuple_element<0, typename T::value_type>::type;
0158 using mapped_type = typename std::tuple_element<1, typename T::value_type>::type;
0159 };
0160
0161
0162 template <typename T>
0163 using GetKeyType = typename MapLikeTypeHelper<T>::key_type;
0164
0165 template <typename T>
0166 using GetMappedType = typename MapLikeTypeHelper<T>::mapped_type;
0167
0168
0169
0170
0171 template <typename T>
0172 using hasMutable_t = typename T::mutable_type;
0173
0174
0175
0176 template <typename T>
0177 using hasObject_t = typename T::object_type;
0178
0179
0180
0181 template <typename T>
0182 constexpr static bool isMutableHandleType = det::is_detected_v<hasObject_t, std::remove_reference_t<T>>;
0183
0184
0185
0186 template <typename T>
0187 constexpr static bool isDefaultHandleType = det::is_detected_v<hasMutable_t, std::remove_reference_t<T>>;
0188
0189
0190
0191
0192
0193
0194 template <typename T>
0195 using GetDefaultHandleType =
0196 typename det::detected_or<std::remove_reference_t<T>, hasObject_t, std::remove_reference_t<T>>::type;
0197
0198
0199
0200
0201
0202
0203 template <typename T>
0204 using GetMutableHandleType =
0205 typename det::detected_or<std::remove_reference_t<T>, hasMutable_t, std::remove_reference_t<T>>::type;
0206
0207
0208
0209 template <typename Tuple>
0210 using TupleOfMutableTypes = typename ToTupleOfTemplateHelper<GetMutableHandleType, Tuple>::type;
0211
0212
0213 template <typename T>
0214 using hasInterface_t = typename T::interfaced_types;
0215
0216
0217
0218
0219
0220 template <typename T>
0221 constexpr static bool isInterfaceType = det::is_detected_v<hasInterface_t, std::remove_reference_t<T>>;
0222
0223
0224
0225 template <typename T, typename U, typename isInterface = std::bool_constant<isInterfaceType<T>>>
0226 struct InterfaceInitializerHelper {};
0227
0228
0229
0230 template <typename T, typename U>
0231 struct InterfaceInitializerHelper<T, U, std::bool_constant<true>>
0232 : std::bool_constant<T::template isInitializableFrom<U>> {};
0233
0234
0235 template <typename T, typename U>
0236 struct InterfaceInitializerHelper<T, U, std::bool_constant<false>> : std::false_type {};
0237
0238
0239
0240 template <typename T, typename U>
0241 constexpr static bool isInterfaceInitializableFrom = InterfaceInitializerHelper<T, U>::value;
0242
0243 }
0244
0245
0246 class CollectionBase;
0247
0248
0249 template <typename T>
0250 concept CollectionType = !std::is_abstract_v<T> && std::derived_from<T, CollectionBase> &&
0251 std::default_initializable<T> && std::destructible<T> && std::movable<T> && !std::copyable<T> &&
0252 std::ranges::random_access_range<T> && requires(T t, const T ct) {
0253
0254 { T::typeName } -> std::convertible_to<std::string_view>;
0255 { std::bool_constant<(T::typeName, true)>() } -> std::same_as<std::true_type>;
0256 { T::valueTypeName } -> std::convertible_to<std::string_view>;
0257 {
0258 std::bool_constant<(T::valueTypeName, true)>()
0259 } -> std::same_as<std::true_type>;
0260 { T::dataTypeName } -> std::convertible_to<std::string_view>;
0261 { std::bool_constant<(T::dataTypeName, true)>() } -> std::same_as<std::true_type>;
0262
0263 typename T::value_type;
0264 typename T::mutable_type;
0265 requires std::convertible_to<typename T::mutable_type, typename T::value_type>;
0266 typename T::difference_type;
0267 requires std::signed_integral<typename T::difference_type>;
0268 typename T::size_type;
0269 requires std::unsigned_integral<typename T::size_type>;
0270 typename T::const_iterator;
0271 requires std::random_access_iterator<typename T::const_iterator>;
0272 typename T::iterator;
0273 requires std::random_access_iterator<typename T::iterator>;
0274 typename T::const_reverse_iterator;
0275 requires std::random_access_iterator<typename T::const_reverse_iterator>;
0276 typename T::reverse_iterator;
0277 requires std::random_access_iterator<typename T::reverse_iterator>;
0278
0279 requires std::same_as<std::remove_reference_t<decltype(t.create())>,
0280 typename T::mutable_type>;
0281
0282 { t.push_back(std::declval<std::add_lvalue_reference_t<std::add_const_t<typename T::mutable_type>>>()) };
0283 { t.push_back(std::declval<std::add_lvalue_reference_t<std::add_const_t<typename T::value_type>>>()) };
0284 { t.begin() } -> std::same_as<typename T::iterator>;
0285 { t.cbegin() } -> std::same_as<typename T::const_iterator>;
0286 { ct.begin() } -> std::same_as<typename T::const_iterator>;
0287 { t.end() } -> std::same_as<typename T::iterator>;
0288 { t.cend() } -> std::same_as<typename T::const_iterator>;
0289 { ct.end() } -> std::same_as<typename T::const_iterator>;
0290 { t.rbegin() } -> std::same_as<typename T::reverse_iterator>;
0291 { t.crbegin() } -> std::same_as<typename T::const_reverse_iterator>;
0292 { ct.rbegin() } -> std::same_as<typename T::const_reverse_iterator>;
0293 { t.rend() } -> std::same_as<typename T::reverse_iterator>;
0294 { t.crend() } -> std::same_as<typename T::const_reverse_iterator>;
0295 { ct.rend() } -> std::same_as<typename T::const_reverse_iterator>;
0296
0297
0298 requires std::same_as<std::remove_reference_t<decltype(t[std::declval<typename T::size_type>()])>,
0299 typename T::mutable_type>;
0300 requires std::same_as<std::remove_cvref_t<decltype(ct[std::declval<typename T::size_type>()])>,
0301 typename T::value_type>;
0302 requires std::same_as<std::remove_reference_t<decltype(t.at(std::declval<typename T::size_type>()))>,
0303 typename T::mutable_type>;
0304 requires std::same_as<std::remove_cvref_t<decltype(ct.at(std::declval<typename T::size_type>()))>,
0305 typename T::value_type>;
0306 };
0307
0308 namespace utils {
0309 template <typename... T>
0310 struct TypeList {};
0311 }
0312
0313 }
0314
0315 #endif