Back to home page

EIC code displayed by LXR

 
 

    


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 } // 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 } // namespace det
0049 #endif
0050 
0051 namespace detail {
0052 
0053   /// Helper struct to determine whether a given type T is in a tuple of types
0054   /// that act as a type list in this case
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   /// variable template for determining whether type T is in a tuple with types
0062   /// Ts
0063   template <typename T, typename Tuple>
0064   static constexpr bool isInTuple = TypeInTupleHelper<T, Tuple>::value;
0065 
0066   /// Helper struct to turn a tuple of types into a tuple of a template of types, e.g.
0067   ///
0068   /// std::tuple<int, float> -> std::tuple<std::vector<int>, std::vector<float>>
0069   /// if the passed template is std::vector
0070   ///
0071   /// @note making the template template parameter to Template variadic because
0072   /// clang will not be satisfied otherwise if we use it with, e.g. std::vector.
0073   /// This will also make root dictionary generation fail. GCC works without this
0074   /// small workaround and is standard compliant in this case, whereas clang is
0075   /// not.
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   /// Type alias to turn a tuple of types into a tuple of vector of types
0085   template <typename Tuple>
0086   using TupleOfVector = typename ToTupleOfTemplateHelper<std::vector, Tuple>::type;
0087 
0088   /// Alias template to get the type of a tuple resulting from a concatenation of
0089   /// tuples
0090   /// See: https://devblogs.microsoft.com/oldnewthing/20200622-00/?p=103900
0091   template <typename... Tuples>
0092   using TupleCatType = decltype(std::tuple_cat(std::declval<Tuples>()...));
0093 
0094   /// variable template for determining whether the type T is in the tuple of all
0095   /// types or in the tuple of all vector of the passed types
0096   template <typename T, typename Tuple>
0097   static constexpr bool isAnyOrVectorOf = isInTuple<T, TupleCatType<Tuple, TupleOfVector<Tuple>>>;
0098 
0099   /// Helper struct to extract the type from a std::vector or return the
0100   /// original type if it is not a vector. Works only for "simple" types and does
0101   /// not strip const-ness
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   /// Helper struct to detect whether a type is a std::vector
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   /// Alias template for deciding whether the passed type T is a vector or not
0123   template <typename T>
0124   static constexpr bool isVector = IsVectorHelper<T>::value;
0125 
0126   /// Helper struct to detect whether a type is a std::map or std::unordered_map
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   /// Alias template for deciding whether the passed type T is a map or
0137   /// unordered_map
0138   template <typename T>
0139   static constexpr bool isMap = IsMapHelper<T>::value;
0140 
0141   /// Helper struct to homogenize the (type) access for things that behave like
0142   /// maps, e.g. vectors of pairs (and obviously maps).
0143   ///
0144   /// @note This is not SFINAE friendly.
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   /// Specialization for actual maps
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   /// Specialization for vector of pairs / tuples (of size 2)
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   /// Type aliases for easier usage in actual code
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   /// Detector for checking the existence of a mutable_type type member. Used to
0171   /// determine whether T is (or could be) a podio generated default (immutable)
0172   /// handle.
0173   template <typename T>
0174   using hasMutable_t = typename T::mutable_type;
0175 
0176   /// Detector for checking the existence of an object_type type member. Used to
0177   /// determine whether T is (or could be) a podio generated mutable handle.
0178   template <typename T>
0179   using hasObject_t = typename T::object_type;
0180 
0181   /// Variable template for determining whether type T is a podio generated
0182   /// handle class.
0183   ///
0184   /// @note this basically just checks the existence of the mutable_type and
0185   /// object_type type members, so it is rather easy to fool this check if one
0186   /// wanted to. However, for our purposes we mainly need it for a static_assert
0187   /// to have more understandable compilation error message.
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   /// Variable template for obtaining the default handle type from any podio
0192   /// generated handle type.
0193   ///
0194   /// If T is already a default handle, this will return T, if T is a mutable
0195   /// handle it will return T::object_type.
0196   template <typename T>
0197   using GetDefaultHandleType = typename det::detected_or<T, hasObject_t, T>::type;
0198 
0199   /// Variable template for obtaining the mutable handle type from any podio
0200   /// generated handle type.
0201   ///
0202   /// If T is already a mutable handle, this will return T, if T is a default
0203   /// handle it will return T::mutable_type.
0204   template <typename T>
0205   using GetMutableHandleType = typename det::detected_or<T, hasMutable_t, T>::type;
0206 
0207   /// Helper type alias to transform a tuple of handle types to a tuple of
0208   /// mutable handle types.
0209   template <typename Tuple>
0210   using TupleOfMutableTypes = typename ToTupleOfTemplateHelper<GetMutableHandleType, Tuple>::type;
0211 
0212 } // namespace detail
0213 
0214 // forward declaration to be able to use it below
0215 class CollectionBase;
0216 
0217 /// Alias template for checking whether a passed type T inherits from podio::CollectionBase
0218 template <typename T>
0219 static constexpr bool isCollection = std::is_base_of_v<CollectionBase, T>;
0220 
0221 } // namespace podio
0222 
0223 #endif // PODIO_UTILITIES_TYPEHELPERS_H