Back to home page

EIC code displayed by LXR

 
 

    


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 } // namespace det
0017 #else
0018 // Implement the minimal feature set we need
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   } // namespace detail
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 } // namespace det
0052 #endif
0053 
0054 namespace detail {
0055 
0056   /// Helper struct to determine whether a given type T is in a tuple of types
0057   /// that act as a type list in this case
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   /// variable template for determining whether type T is in a tuple with types
0065   /// Ts
0066   template <typename T, typename Tuple>
0067   static constexpr bool isInTuple = TypeInTupleHelper<T, Tuple>::value;
0068 
0069   /// Helper struct to turn a tuple of types into a tuple of a template of types, e.g.
0070   ///
0071   /// std::tuple<int, float> -> std::tuple<std::vector<int>, std::vector<float>>
0072   /// if the passed template is std::vector
0073   ///
0074   /// @note making the template template parameter to Template variadic because
0075   /// clang will not be satisfied otherwise if we use it with, e.g. std::vector.
0076   /// This will also make root dictionary generation fail. GCC works without this
0077   /// small workaround and is standard compliant in this case, whereas clang is
0078   /// not.
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   /// Type alias to turn a tuple of types into a tuple of vector of types
0088   template <typename Tuple>
0089   using TupleOfVector = typename ToTupleOfTemplateHelper<std::vector, Tuple>::type;
0090 
0091   /// Alias template to get the type of a tuple resulting from a concatenation of
0092   /// tuples
0093   /// See: https://devblogs.microsoft.com/oldnewthing/20200622-00/?p=103900
0094   template <typename... Tuples>
0095   using TupleCatType = decltype(std::tuple_cat(std::declval<Tuples>()...));
0096 
0097   /// variable template for determining whether the type T is in the tuple of all
0098   /// types or in the tuple of all vector of the passed types
0099   template <typename T, typename Tuple>
0100   static constexpr bool isAnyOrVectorOf = isInTuple<T, TupleCatType<Tuple, TupleOfVector<Tuple>>>;
0101 
0102   /// Helper struct to extract the type from a std::vector or return the
0103   /// original type if it is not a vector. Works only for "simple" types and does
0104   /// not strip const-ness
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   /// Helper struct to detect whether a type is a std::vector
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   /// Alias template for deciding whether the passed type T is a vector or not
0126   template <typename T>
0127   static constexpr bool isVector = IsVectorHelper<T>::value;
0128 
0129   /// Helper struct to detect whether a type is a std::map or std::unordered_map
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   /// Alias template for deciding whether the passed type T is a map or
0140   /// unordered_map
0141   template <typename T>
0142   static constexpr bool isMap = IsMapHelper<T>::value;
0143 
0144   /// Helper struct to homogenize the (type) access for things that behave like
0145   /// maps, e.g. vectors of pairs (and obviously maps).
0146   ///
0147   /// @note This is not SFINAE friendly.
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   /// Specialization for actual maps
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   /// Specialization for vector of pairs / tuples (of size 2)
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   /// Type aliases for easier usage in actual code
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   /// Detector for checking the existence of a mutable_type type member. Used to
0174   /// determine whether T is (or could be) a podio generated default (immutable)
0175   /// handle.
0176   template <typename T>
0177   using hasMutable_t = typename T::mutable_type;
0178 
0179   /// Detector for checking the existence of an object_type type member. Used to
0180   /// determine whether T is (or could be) a podio generated mutable handle.
0181   template <typename T>
0182   using hasObject_t = typename T::object_type;
0183 
0184   /// Detector for checking the existence of a collection_type type member.
0185   template <typename T>
0186   using hasCollection_t = typename T::collection_type;
0187 
0188   /// Variable template for determining whether type T is a podio generated
0189   /// mutable handle class
0190   template <typename T>
0191   constexpr static bool isMutableHandleType = det::is_detected_v<hasObject_t, std::remove_reference_t<T>>;
0192 
0193   /// Variable template for determining whether type T is a podio generated
0194   /// default handle class
0195   template <typename T>
0196   constexpr static bool isDefaultHandleType = det::is_detected_v<hasMutable_t, std::remove_reference_t<T>>;
0197 
0198   /// Variable template for determining whether type T is a podio generated
0199   /// handle class.
0200   ///
0201   /// @note this basically just checks the existence of the mutable_type and
0202   /// object_type type members, so it is rather easy to fool this check if one
0203   /// wanted to. However, for our purposes we mainly need it for a static_assert
0204   /// to have more understandable compilation error message.
0205   template <typename T>
0206   constexpr static bool isPodioType = isDefaultHandleType<T> || isMutableHandleType<T>;
0207 
0208   /// Variable template for obtaining the default handle type from any podio
0209   /// generated handle type.
0210   ///
0211   /// If T is already a default handle, this will return T, if T is a mutable
0212   /// handle it will return T::object_type.
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   /// Variable template for obtaining the mutable handle type from any podio
0218   /// generated handle type.
0219   ///
0220   /// If T is already a mutable handle, this will return T, if T is a default
0221   /// handle it will return T::mutable_type.
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   /// Variable template for obtaining the collection type from any podio
0227   /// generated handle type
0228   template <typename T>
0229   using GetCollectionType = det::detected_t<hasCollection_t, std::remove_reference_t<T>>;
0230 
0231   /// Helper type alias to transform a tuple of handle types to a tuple of
0232   /// mutable handle types.
0233   template <typename Tuple>
0234   using TupleOfMutableTypes = typename ToTupleOfTemplateHelper<GetMutableHandleType, Tuple>::type;
0235 
0236   /// Detector for checking for the existence of an interfaced_type type member
0237   template <typename T>
0238   using hasInterface_t = typename T::interfaced_types;
0239 
0240   /// Variable template for checking whether the passed type T is an interface
0241   /// type.
0242   ///
0243   /// @note: This simply checks whether T has an interfaced_types type member.
0244   template <typename T>
0245   constexpr static bool isInterfaceType = det::is_detected_v<hasInterface_t, std::remove_reference_t<T>>;
0246 
0247   /// Helper struct to make the detection whether type U can be used to
0248   /// initialize the interface type T in a SFINAE friendly way
0249   template <typename T, typename U, typename isInterface = std::bool_constant<isInterfaceType<T>>>
0250   struct InterfaceInitializerHelper {};
0251 
0252   /// Specialization for actual interface types, including the check whether T
0253   /// is initializable from U
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   /// Specialization for non interface types
0259   template <typename T, typename U>
0260   struct InterfaceInitializerHelper<T, U, std::bool_constant<false>> : std::false_type {};
0261 
0262   /// Variable template for checking whether the passed type T is an interface
0263   /// and can be initialized from type U
0264   template <typename T, typename U>
0265   constexpr static bool isInterfaceInitializableFrom = InterfaceInitializerHelper<T, U>::value;
0266 
0267 } // namespace detail
0268 
0269 // forward declaration to be able to use it below
0270 class CollectionBase;
0271 
0272 /// Alias template for checking whether a passed type T inherits from podio::CollectionBase
0273 template <typename T>
0274 static constexpr bool isCollection = std::is_base_of_v<CollectionBase, T>;
0275 
0276 } // namespace podio
0277 
0278 #endif // PODIO_UTILITIES_TYPEHELPERS_H