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
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 bool operator==(const WeightedObject<T>& other) const {
0026 return other.o == o && other.weight == weight;
0027 }
0028 };
0029
0030
0031 struct ReturnFromTag {};
0032
0033 struct ReturnToTag {};
0034 }
0035
0036
0037
0038 static constexpr detail::links::ReturnFromTag ReturnFrom;
0039
0040
0041 static constexpr detail::links::ReturnToTag ReturnTo;
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
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
0062 LinkNavigator(const LinkCollT& links);
0063
0064
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
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
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
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
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
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
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
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
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{};
0158 std::multimap<ToT, WeightedObject<FromT>> m_to2from{};
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 }
0170
0171 #endif