Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/podio/detail/RelationIOHelpers.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 #ifndef PODIO_DETAIL_RELATIONIOHELPERS_H
0002 #define PODIO_DETAIL_RELATIONIOHELPERS_H
0003 
0004 #include "podio/utilities/TypeHelpers.h"
0005 #include <podio/CollectionBase.h>
0006 
0007 #include <memory>
0008 #include <tuple>
0009 #include <vector>
0010 
0011 namespace podio::detail {
0012 
0013 /// Function template for handling interface types in OneToMultiRelations
0014 ///
0015 /// Effectively this function checks whether the passed collection can be
0016 /// dynamically cast to the collection type of the concrete type and if that is
0017 /// true uses it to construct an interface type and add it to relElements. The
0018 /// function on its own doesn't do anything too meaningful, it is meant to be
0019 /// used in a call to std::apply that goes over all the interfaced types of an
0020 /// interface type.
0021 ///
0022 /// @tparam T The concrete type inside the interface that should be checked.
0023 ///           This effectively is mainly used for tag-dispatch and overload
0024 ///           selection in this context
0025 /// @tparam InterfaceType The interface type (that can be used to interface T)
0026 ///
0027 /// @param relElements The vector to which the interface objects should be added
0028 /// @param coll The collection that holds the actual element
0029 /// @param id The ObjectID of the element that we are currently looking for
0030 template <typename T, typename InterfaceType>
0031 void tryAddTo(T, std::vector<InterfaceType>& relElements, const podio::CollectionBase* coll, const podio::ObjectID id) {
0032   if (auto typedColl = dynamic_cast<const typename T::collection_type*>(coll)) {
0033     const T tmp = (*typedColl)[id.index];
0034     relElements.emplace_back(tmp);
0035   }
0036 }
0037 
0038 /// Helper function for handling interface type relations in OneToManyRelations
0039 ///
0040 /// This function tries all types that are interfaced by the InterfaceType and
0041 /// adds the one that matches to the relations. The main work happens in
0042 /// tryAddTo, this simply wraps everything in a std::apply over all
0043 /// interfaced_types.
0044 ///
0045 /// @tparam InterfaceType The interface type of the Relation
0046 ///
0047 /// @param relElements The vector to which the interface objects should be added
0048 /// @param coll The collection that holds the actual element
0049 /// @param id The ObjectID of the element that we are currently looking for
0050 template <typename InterfaceType>
0051 void addInterfaceToMultiRelation(std::vector<InterfaceType>& relElements, const podio::CollectionBase* coll,
0052                                  const podio::ObjectID id) {
0053   std::apply([&](auto... t) { (tryAddTo(t, relElements, coll, id), ...); }, typename InterfaceType::interfaced_types{});
0054 }
0055 
0056 /// Helper function for adding an object to the OneToManyRelations container
0057 /// when reading back collections
0058 ///
0059 /// This function does the necessary type casting of the passed collection to
0060 /// retrieve the desired object and also takes care of adding the object to the
0061 /// container that holds them for later usage. It handles relations to regular
0062 /// types as well as interface types.
0063 ///
0064 /// This functionality has been lifted from the jinja2 templates, where we now
0065 /// only call it, because we need a template deduction context for making if
0066 /// constexpr work as expected, such that we can dispatch to different
0067 /// implementatoins depending on whether the relation is to an interface type or
0068 /// to a regular type.
0069 ///
0070 /// @note It is expected that the following pre-conditions are met:
0071 ///       - The passed collection is valid (i.e. not a nullptr)
0072 ///       - the collectionID of the passed collection is the same as the one in
0073 ///         the passed ObjectID
0074 ///       - The collection can by casted to the relation type or any of the
0075 ///         interfaced types of the relation
0076 ///
0077 /// @tparam RelType The type of the OneToManyRelation
0078 ///
0079 /// @param relElements The container that holds the objects for the relation and
0080 ///                    which will be used for adding an element from the passed
0081 ///                    collection
0082 /// @param coll The collection from which the object will be obtained after the
0083 ///             necessary type casting
0084 /// @param id The ObjectID of the object that should be retrieved and added.
0085 template <typename RelType>
0086 void addMultiRelation(std::vector<RelType>& relElements, const podio::CollectionBase* coll, const podio::ObjectID id) {
0087   if constexpr (podio::detail::isInterfaceType<RelType>) {
0088     addInterfaceToMultiRelation(relElements, coll, id);
0089   } else {
0090     const auto* typeColl = static_cast<const typename RelType::collection_type*>(coll);
0091     relElements.emplace_back((*typeColl)[id.index]);
0092   }
0093 }
0094 
0095 /// Function template for handling interface types in OneToOneRelations
0096 ///
0097 /// Effectively this function checks whether the passed collection can be
0098 /// dynamically cast to the collection type of the concrete type and if that is
0099 /// true uses it to assign to the passed interface object The function on its
0100 /// own doesn't do anything too meaningful, it is meant to be used in a call to
0101 /// std::apply that goes over all the interfaced types of an interface type.
0102 ///
0103 /// @tparam T The concrete type inside the interface that should be checked.
0104 ///           This effectively is mainly used for tag-dispatch and overload
0105 ///           selection in this context
0106 /// @tparam InterfaceType The interface type (that can be used to interface T)
0107 ///
0108 /// @param relation The object to which the interface object should be assigned
0109 ///                 to
0110 /// @param coll The collection that holds the actual element
0111 /// @param id The ObjectID of the element that we are currently looking for
0112 template <typename T, typename InterfaceType>
0113 void tryAssignTo(T, std::unique_ptr<InterfaceType>& relation, const podio::CollectionBase* coll,
0114                  const podio::ObjectID id) {
0115   if (const auto* typeColl = dynamic_cast<const typename T::collection_type*>(coll)) {
0116     relation = std::make_unique<InterfaceType>((*typeColl)[id.index]);
0117   }
0118 }
0119 
0120 /// Helper function for handling interface type relations in OneToOneRelations
0121 ///
0122 /// This function tries all types that are interfaced by the InterfaceType and
0123 /// that assigns the one thta matches to the relation. The main work happens in
0124 /// tryAssignTo, this simply wraps everything in a std::apply over all
0125 /// interfaced_types.
0126 ///
0127 /// @tparam InterfaceType The interface type of the Relation
0128 ///
0129 /// @param relation The object to which the interface object should be assigned
0130 ///                 to
0131 /// @param coll The collection that holds the actual element
0132 /// @param id The ObjectID of the element that we are currently looking for
0133 template <typename InterfaceType>
0134 void addInterfaceToSingleRelation(std::unique_ptr<InterfaceType>& relation, const podio::CollectionBase* coll,
0135                                   const podio::ObjectID id) {
0136   std::apply([&](auto... t) { (tryAssignTo(t, relation, coll, id), ...); }, typename InterfaceType::interfaced_types{});
0137 }
0138 
0139 /// Helper function for assigning the related object in a OneToOneRelation
0140 ///
0141 /// This function does the necessary type casting of the passed collection to
0142 /// retrieve the desired object and also takes care of assigning the object to
0143 /// the passed pointer that hold it for later usage. It handles relations
0144 /// to regular types as well as interface types.
0145 ///
0146 /// This functionality has been lifted from the jinja2 templates, where we now
0147 /// only call it, because we need a template deduction context for making if
0148 /// constexpr work as expected, such that we can dispatch to different
0149 /// implementatoins depending on whether the relation is to an interface type or
0150 /// to a regular type.
0151 ///
0152 /// @note It is expected that the following pre-conditions are met:
0153 ///       - The passed collection is valid (i.e. not a nullptr)
0154 ///       - the collectionID of the passed collection is the same as the one in
0155 ///         the passed ObjectID
0156 ///       - The collection can by casted to the relation type or any of the
0157 ///         interfaced types of the relation
0158 ///
0159 /// @tparam RelType The type of the OneToManyRelation
0160 ///
0161 /// @param relation The pointer to which we should assign the related object
0162 ///                 that is retrieved from the passed collection
0163 /// @param coll The collection from which the object will be obtained after the
0164 ///             necessary type casting
0165 /// @param id The ObjectID of the object that should be retrieved and added.
0166 template <typename RelType>
0167 void addSingleRelation(std::unique_ptr<RelType>& relation, const podio::CollectionBase* coll,
0168                        const podio::ObjectID id) {
0169   if constexpr (podio::detail::isInterfaceType<RelType>) {
0170     addInterfaceToSingleRelation(relation, coll, id);
0171   } else {
0172     const auto* typeColl = static_cast<const typename RelType::collection_type*>(coll);
0173     relation = std::make_unique<RelType>((*typeColl)[id.index]);
0174   }
0175 }
0176 
0177 } // namespace podio::detail
0178 
0179 #endif // PODIO_DETAIL_RELATIONIOHELPERS_H