Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-05-11 09:02:30

0001 #ifndef PODIO_LINKNAVIGATOR_H
0002 #define PODIO_LINKNAVIGATOR_H
0003 
0004 #include <map>
0005 #include <tuple>
0006 #include <type_traits>
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     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 ReturnFromTag {};
0032   /// Simple struct tag for overload selection in LinkNavigator below
0033   struct ReturnToTag {};
0034 } // namespace detail::links
0035 
0036 /// Tag variable to select the lookup of *From* objects have links with a *To*
0037 /// object in podio::LinkNavigator::getLinked
0038 static constexpr detail::links::ReturnFromTag ReturnFrom;
0039 /// Tag variable to select the lookup of *To* objects that have links with a
0040 /// *From* object in podio::LinkNavigator::getLinked
0041 static constexpr detail::links::ReturnToTag ReturnTo;
0042 
0043 /// A helper class to more easily handle one-to-many links.
0044 ///
0045 /// Internally simply populates two maps in its constructor and then queries
0046 /// them to retrieve objects that are linked with another.
0047 ///
0048 /// @note There are no guarantees on the order of the objects in these maps.
0049 /// Hence, there are also no guarantees on the order of the returned objects,
0050 /// even if there inherintly is an order to them in the underlying links
0051 /// collection.
0052 template <typename LinkCollT>
0053 class LinkNavigator {
0054   using FromT = typename LinkCollT::from_type;
0055   using ToT = typename LinkCollT::to_type;
0056 
0057   template <typename T>
0058   using WeightedObject = detail::links::WeightedObject<T>;
0059 
0060 public:
0061   /// Construct a navigator from an link collection
0062   LinkNavigator(const LinkCollT& links);
0063 
0064   /// We do only construct from a collection
0065   LinkNavigator() = delete;
0066   LinkNavigator(const LinkNavigator&) = default;
0067   LinkNavigator& operator=(const LinkNavigator&) = default;
0068   LinkNavigator(LinkNavigator&&) = default;
0069   LinkNavigator& operator=(LinkNavigator&&) = default;
0070   ~LinkNavigator() = default;
0071 
0072   /// Get all the *From* objects and weights that have links with the passed
0073   /// object
0074   ///
0075   /// You will get this overload if you pass the podio::ReturnFrom tag as second
0076   /// argument
0077   ///
0078   /// @note This overload works always, even if the LinkCollection that was used
0079   /// to construct this instance of the LinkNavigator has the same From and To
0080   /// types.
0081   ///
0082   /// @param object The object that is labeled *To* in the link
0083   /// @param . tag variable for selecting this overload
0084   ///
0085   /// @returns A vector of all objects and their weights that have links with
0086   ///          the passed object
0087   std::vector<WeightedObject<FromT>> getLinked(const ToT& object, podio::detail::links::ReturnFromTag) const {
0088     const auto& [begin, end] = m_to2from.equal_range(object);
0089     std::vector<WeightedObject<FromT>> result;
0090     result.reserve(std::distance(begin, end));
0091 
0092     for (auto it = begin; it != end; ++it) {
0093       result.emplace_back(it->second);
0094     }
0095     return result;
0096   }
0097 
0098   /// Get all the *From* objects and weights that have links with the passed
0099   /// object
0100   ///
0101   /// @note This overload will automatically do the right thing (TM) in case the
0102   /// LinkCollection that has been passed to construct this LinkNavigator has
0103   /// different From and To types.
0104   ///
0105   /// @param object The object that is labeled *To* in the link
0106   ///
0107   /// @returns A vector of all objects and their weights that have links with
0108   ///          the passed object
0109   template <typename ToU = ToT>
0110   std::enable_if_t<!std::is_same_v<FromT, ToU>, std::vector<WeightedObject<FromT>>> getLinked(const ToT& object) const {
0111     return getLinked(object, podio::ReturnFrom);
0112   }
0113 
0114   /// Get all the *To* objects and weights that have links with the passed
0115   /// object
0116   ///
0117   /// You will get this overload if you pass the podio::ReturnTo tag as second
0118   /// argument
0119   ///
0120   /// @note This overload works always, even if the LinkCollection that was used
0121   /// to construct this instance of the LinkNavigator has the same From and To
0122   /// types.
0123   ///
0124   /// @param object The object that is labeled *From* in the link
0125   /// @param . tag variable for selecting this overload
0126   ///
0127   /// @returns A vector of all objects and their weights that have links with
0128   ///          the passed object
0129   std::vector<WeightedObject<ToT>> getLinked(const FromT& object, podio::detail::links::ReturnToTag) const {
0130     const auto& [begin, end] = m_from2to.equal_range(object);
0131     std::vector<WeightedObject<ToT>> result;
0132     result.reserve(std::distance(begin, end));
0133 
0134     for (auto it = begin; it != end; ++it) {
0135       result.emplace_back(it->second);
0136     }
0137     return result;
0138   }
0139 
0140   /// Get all the *To* objects and weights that have links with the passed
0141   /// object
0142   ///
0143   /// @note This overload will automatically do the right thing (TM) in case the
0144   /// LinkCollection that has been passed to construct this LinkNavigator has
0145   /// different From and To types.
0146   ///
0147   /// @param object The object that is labeled *From* in the link
0148   ///
0149   /// @returns A vector of all objects and their weights that have links with
0150   ///          the passed object
0151   template <typename FromU = FromT>
0152   std::enable_if_t<!std::is_same_v<FromU, ToT>, std::vector<WeightedObject<ToT>>> getLinked(const FromT& object) const {
0153     return getLinked(object, podio::ReturnTo);
0154   }
0155 
0156 private:
0157   std::multimap<FromT, WeightedObject<ToT>> m_from2to{}; ///< Map the from to the to objects
0158   std::multimap<ToT, WeightedObject<FromT>> m_to2from{}; ///< Map the to to the from objects
0159 };
0160 
0161 template <typename LinkCollT>
0162 LinkNavigator<LinkCollT>::LinkNavigator(const LinkCollT& links) {
0163   for (const auto& [from, to, weight] : links) {
0164     m_from2to.emplace(std::piecewise_construct, std::forward_as_tuple(from), std::forward_as_tuple(to, weight));
0165     m_to2from.emplace(std::piecewise_construct, std::forward_as_tuple(to), std::forward_as_tuple(from, weight));
0166   }
0167 }
0168 
0169 } // namespace podio
0170 
0171 #endif // PODIO_LINKNAVIGATOR_H