Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-24 09:18:39

0001 #ifndef PODIO_LINKNAVIGATOR_H
0002 #define PODIO_LINKNAVIGATOR_H
0003 
0004 #include <concepts>
0005 #include <map>
0006 #include <tuple>
0007 #include <utility>
0008 #include <vector>
0009 
0010 namespace podio {
0011 
0012 namespace detail::links {
0013   /// A small struct that simply bundles an object and its weight for a more
0014   /// convenient return value for the LinkNavigator
0015   ///
0016   /// @note In most uses the names of the members should not really matter as it
0017   /// is possible to us this via structured bindings
0018   template <typename T>
0019   struct WeightedObject {
0020     WeightedObject(T obj, float w) : o(obj), weight(w) {
0021     }
0022     T o;          ///< The object
0023     float weight; ///< The weight in the link
0024 
0025     constexpr bool operator==(const WeightedObject<T>& other) const {
0026       return other.o == o && other.weight == weight;
0027     }
0028   };
0029 
0030   /// Simple struct tag for overload selection in LinkNavigator below
0031   struct [[deprecated("The tagged versions of getLinked are deprecated use getLinkedFrom instead")]] ReturnFromTag {};
0032   /// Simple struct tag for overload selection in LinkNavigator below
0033   struct [[deprecated("The tagged versions of getLinked are deprecated use getLinkedTo instead")]] ReturnToTag {};
0034 } // namespace detail::links
0035 
0036 /// NOTE: This can go at the same time as the deprecated tags below are removed
0037 #if !defined(__CLING__)
0038   #define INLCONSTEXPR inline constexpr
0039 #else
0040   #define INLCONSTEXPR
0041 #endif
0042 /// Tag variable to select the lookup of *From* objects have links with a *To*
0043 /// object in podio::LinkNavigator::getLinked
0044 // INLCONSTEXPR detail::links::ReturnFromTag ReturnFrom;
0045 [[deprecated("The tagged versions of getLinked are deprecated use getLinkedFrom instead")]] INLCONSTEXPR
0046     detail::links::ReturnFromTag ReturnFrom;
0047 /// Tag variable to select the lookup of *To* objects that have links with a
0048 /// *From* object in podio::LinkNavigator::getLinked
0049 // INLCONSTEXPR detail::links::ReturnToTag ReturnTo;
0050 [[deprecated("The tagged versions of getLinked are deprecated use getLinkedTo instead")]] INLCONSTEXPR
0051     detail::links::ReturnToTag ReturnTo;
0052 #undef INLCONSTEXPR
0053 
0054 /// A helper class to more easily handle one-to-many links.
0055 ///
0056 /// Internally simply populates two maps in its constructor and then queries
0057 /// them to retrieve objects that are linked with another.
0058 ///
0059 /// @note There are no guarantees on the order of the objects in these maps.
0060 /// Hence, there are also no guarantees on the order of the returned objects,
0061 /// even if there inherintly is an order to them in the underlying links
0062 /// collection.
0063 template <typename LinkCollT>
0064 class LinkNavigator {
0065   using FromT = typename LinkCollT::from_type;
0066   using ToT = typename LinkCollT::to_type;
0067 
0068   template <typename T>
0069   using WeightedObject = detail::links::WeightedObject<T>;
0070 
0071 public:
0072   /// Construct a navigator from an link collection
0073   LinkNavigator(const LinkCollT& links);
0074 
0075   /// We do only construct from a collection
0076   LinkNavigator() = delete;
0077   LinkNavigator(const LinkNavigator&) = default;
0078   LinkNavigator& operator=(const LinkNavigator&) = default;
0079   LinkNavigator(LinkNavigator&&) = default;
0080   LinkNavigator& operator=(LinkNavigator&&) = default;
0081   ~LinkNavigator() = default;
0082 
0083   /// Get all the *From* objects and weights that have links with the passed
0084   /// object
0085   ///
0086   /// You will get this overload if you pass the podio::ReturnFrom tag as second
0087   /// argument
0088   ///
0089   /// @note This overload works always, even if the LinkCollection that was used
0090   /// to construct this instance of the LinkNavigator has the same From and To
0091   /// types.
0092   ///
0093   /// @param object The object that is labeled *To* in the link
0094   /// @param . tag variable for selecting this overload
0095   ///
0096   /// @returns A vector of all objects and their weights that have links with
0097   ///          the passed object
0098   std::vector<WeightedObject<FromT>> getLinkedFrom(const ToT& object) const {
0099     const auto& [begin, end] = m_to2from.equal_range(object);
0100     std::vector<WeightedObject<FromT>> result;
0101     result.reserve(std::distance(begin, end));
0102 
0103     for (auto it = begin; it != end; ++it) {
0104       result.emplace_back(it->second);
0105     }
0106     return result;
0107   }
0108 
0109   [[deprecated("Use getLinkedFrom instead")]]
0110   std::vector<WeightedObject<FromT>> getLinked(const ToT& object, podio::detail::links::ReturnFromTag) const {
0111     return getLinkedFrom(object);
0112   }
0113 
0114   [[deprecated("Use getLinkedFrom instead")]]
0115   std::vector<WeightedObject<FromT>> getLinked(const typename ToT::mutable_type& object,
0116                                                podio::detail::links::ReturnFromTag) const {
0117     return getLinkedFrom(ToT(object));
0118   }
0119 
0120   /// Get all the *From* objects and weights that have links with the passed
0121   /// object
0122   ///
0123   /// @note This overload will automatically do the right thing (TM) in case the
0124   /// LinkCollection that has been passed to construct this LinkNavigator has
0125   /// different From and To types.
0126   ///
0127   /// @param object The object that is labeled *To* in the link
0128   ///
0129   /// @returns A vector of all objects and their weights that have links with
0130   ///          the passed object
0131   template <typename ToU = ToT>
0132     requires(!std::same_as<FromT, ToU>)
0133   std::vector<WeightedObject<FromT>> getLinked(const ToT& object) const {
0134     return getLinkedFrom(object);
0135   }
0136 
0137   /// Overload for cppyy that makes things work with mutable handles
0138   template <typename ToU = ToT>
0139     requires(!std::same_as<FromT, ToU>)
0140   std::vector<WeightedObject<FromT>> getLinked(const typename ToT::mutable_type& object) const {
0141     return getLinkedFrom(ToT(object));
0142   }
0143 
0144   /// Get all the *To* objects and weights that have links with the passed
0145   /// object
0146   ///
0147   /// You will get this overload if you pass the podio::ReturnTo tag as second
0148   /// argument
0149   ///
0150   /// @note This overload works always, even if the LinkCollection that was used
0151   /// to construct this instance of the LinkNavigator has the same From and To
0152   /// types.
0153   ///
0154   /// @param object The object that is labeled *From* in the link
0155   /// @param . tag variable for selecting this overload
0156   ///
0157   /// @returns A vector of all objects and their weights that have links with
0158   ///          the passed object
0159   std::vector<WeightedObject<ToT>> getLinkedTo(const FromT& object) const {
0160     const auto& [begin, end] = m_from2to.equal_range(object);
0161     std::vector<WeightedObject<ToT>> result;
0162     result.reserve(std::distance(begin, end));
0163 
0164     for (auto it = begin; it != end; ++it) {
0165       result.emplace_back(it->second);
0166     }
0167     return result;
0168   }
0169 
0170   [[deprecated("Use getLinkedTo instead")]]
0171   std::vector<WeightedObject<ToT>> getLinked(const FromT& object, podio::detail::links::ReturnToTag) const {
0172     return getLinkedTo(object);
0173   }
0174 
0175   [[deprecated("Use getLinkedTo instead")]]
0176   std::vector<WeightedObject<ToT>> getLinked(const typename FromT::mutable_type& object,
0177                                              podio::detail::links::ReturnToTag) const {
0178     return getLinkedTo(FromT(object));
0179   }
0180 
0181   /// Get all the *To* objects and weights that have links with the passed
0182   /// object
0183   ///
0184   /// @note This overload will automatically do the right thing (TM) in case the
0185   /// LinkCollection that has been passed to construct this LinkNavigator has
0186   /// different From and To types.
0187   ///
0188   /// @param object The object that is labeled *From* in the link
0189   ///
0190   /// @returns A vector of all objects and their weights that have links with
0191   ///          the passed object
0192   template <typename FromU = FromT>
0193     requires(!std::same_as<FromU, ToT>)
0194   std::vector<WeightedObject<ToT>> getLinked(const FromT& object) const {
0195     return getLinkedTo(object);
0196   }
0197 
0198   /// Overload for cppyy that makes things work with mutable handles
0199   template <typename FromU = FromT>
0200     requires(!std::same_as<FromU, ToT>)
0201   std::vector<WeightedObject<ToT>> getLinked(const typename FromT::mutable_type& object) const {
0202     return getLinkedTo(FromT(object));
0203   }
0204 
0205 private:
0206   std::multimap<FromT, WeightedObject<ToT>> m_from2to{}; ///< Map the from to the to objects
0207   std::multimap<ToT, WeightedObject<FromT>> m_to2from{}; ///< Map the to to the from objects
0208 };
0209 
0210 template <typename LinkCollT>
0211 LinkNavigator<LinkCollT>::LinkNavigator(const LinkCollT& links) {
0212   for (const auto& [from, to, weight] : links) {
0213     m_from2to.emplace(std::piecewise_construct, std::forward_as_tuple(from), std::forward_as_tuple(to, weight));
0214     m_to2from.emplace(std::piecewise_construct, std::forward_as_tuple(to), std::forward_as_tuple(from, weight));
0215   }
0216 }
0217 
0218 } // namespace podio
0219 
0220 #endif // PODIO_LINKNAVIGATOR_H