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
0014
0015
0016
0017
0018 template <typename T>
0019 struct WeightedObject {
0020 WeightedObject(T obj, float w) : o(obj), weight(w) {
0021 }
0022 T o;
0023 float weight;
0024
0025 constexpr bool operator==(const WeightedObject<T>& other) const {
0026 return other.o == o && other.weight == weight;
0027 }
0028 };
0029
0030
0031 struct [[deprecated("The tagged versions of getLinked are deprecated use getLinkedFrom instead")]] ReturnFromTag {};
0032
0033 struct [[deprecated("The tagged versions of getLinked are deprecated use getLinkedTo instead")]] ReturnToTag {};
0034 }
0035
0036
0037 #if !defined(__CLING__)
0038 #define INLCONSTEXPR inline constexpr
0039 #else
0040 #define INLCONSTEXPR
0041 #endif
0042
0043
0044
0045 [[deprecated("The tagged versions of getLinked are deprecated use getLinkedFrom instead")]] INLCONSTEXPR
0046 detail::links::ReturnFromTag ReturnFrom;
0047
0048
0049
0050 [[deprecated("The tagged versions of getLinked are deprecated use getLinkedTo instead")]] INLCONSTEXPR
0051 detail::links::ReturnToTag ReturnTo;
0052 #undef INLCONSTEXPR
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
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
0073 LinkNavigator(const LinkCollT& links);
0074
0075
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
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
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
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
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
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
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
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
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
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
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{};
0207 std::multimap<ToT, WeightedObject<FromT>> m_to2from{};
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 }
0219
0220 #endif