Warning, file /include/podio/detail/Link.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_LINK_H
0002 #define PODIO_DETAIL_LINK_H
0003
0004 #include "podio/detail/LinkFwd.h"
0005 #include "podio/detail/LinkObj.h"
0006 #include "podio/utilities/MaybeSharedPtr.h"
0007 #include "podio/utilities/TypeHelpers.h"
0008
0009 #ifdef PODIO_JSON_OUTPUT
0010 #include "nlohmann/json.hpp"
0011 #endif
0012
0013 #include <ostream>
0014 #include <utility> // std::swap
0015
0016 namespace podio {
0017
0018
0019
0020
0021 template <typename FromT, typename ToT, bool Mutable>
0022 class LinkT {
0023
0024
0025
0026 static_assert(std::is_same_v<detail::GetDefaultHandleType<FromT>, FromT>,
0027 "Links need to be instantiated with the default types!");
0028 static_assert(std::is_same_v<detail::GetDefaultHandleType<ToT>, ToT>,
0029 "Links need to be instantiated with the default types!");
0030
0031 using LinkObjT = LinkObj<FromT, ToT>;
0032 friend LinkCollection<FromT, ToT>;
0033 friend LinkCollectionIteratorT<FromT, ToT, Mutable>;
0034 friend LinkT<FromT, ToT, !Mutable>;
0035
0036
0037
0038 template <typename FromU, typename ToU>
0039 constexpr static bool sameTypes = std::is_same_v<FromU, FromT> && std::is_same_v<ToU, ToT>;
0040
0041
0042
0043 template <typename T>
0044 static constexpr bool isFromOrToT = detail::isInTuple<T, std::tuple<FromT, ToT>>;
0045
0046
0047
0048 template <typename T>
0049 static constexpr bool isMutableFromOrToT =
0050 detail::isInTuple<T,
0051 std::tuple<FromT, ToT, detail::GetMutableHandleType<FromT>, detail::GetMutableHandleType<ToT>>>;
0052
0053 public:
0054 using mutable_type = podio::MutableLink<FromT, ToT>;
0055 using value_type = podio::Link<FromT, ToT>;
0056 using collection_type = podio::LinkCollection<FromT, ToT>;
0057
0058
0059 LinkT() : m_obj(new LinkObjT{}, podio::utils::MarkOwned) {
0060 }
0061
0062
0063 LinkT(float weight) : m_obj(new LinkObjT{}, podio::utils::MarkOwned) {
0064 m_obj->data.weight = weight;
0065 }
0066
0067
0068 LinkT(const LinkT& other) = default;
0069
0070
0071 LinkT& operator=(LinkT other) {
0072 swap(*this, other);
0073 return *this;
0074 }
0075
0076
0077 template <typename FromU, typename ToU, typename = std::enable_if_t<Mutable && sameTypes<FromU, ToU>>>
0078 operator LinkT<FromU, ToU, false>() const {
0079 return Link<FromU, ToU>(m_obj);
0080 }
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090 template <typename FromU = FromT, typename ToU = ToT, typename = std::enable_if_t<sameTypes<FromU, ToU>>>
0091 MutableLink<FromU, ToU> clone(bool cloneRelations = true) const {
0092 auto tmp = new LinkObjT(podio::ObjectID{}, m_obj->data);
0093 if (cloneRelations) {
0094 if (m_obj->m_from) {
0095 tmp->m_from = std::make_unique<FromT>(*m_obj->m_from);
0096 }
0097 if (m_obj->m_to) {
0098 tmp->m_to = std::make_unique<ToT>(*m_obj->m_to);
0099 }
0100 }
0101 return MutableLink<FromU, ToU>(podio::utils::MaybeSharedPtr(tmp, podio::utils::MarkOwned));
0102 }
0103
0104
0105 template <bool Mut = Mutable, typename = std::enable_if_t<!Mut && !Mutable>>
0106 static Link<FromT, ToT> makeEmpty() {
0107 return {nullptr};
0108 }
0109
0110
0111 ~LinkT() = default;
0112
0113
0114 float getWeight() const {
0115 return m_obj->data.weight;
0116 }
0117
0118
0119 template <bool Mut = Mutable, typename = std::enable_if_t<Mut && Mutable>>
0120 void setWeight(float value) {
0121 m_obj->data.weight = value;
0122 }
0123
0124
0125 const FromT getFrom() const {
0126 if (!m_obj->m_from) {
0127 return FromT::makeEmpty();
0128 }
0129 return FromT(*(m_obj->m_from));
0130 }
0131
0132
0133
0134
0135
0136
0137 template <typename FromU,
0138 std::enable_if_t<Mutable && std::is_same_v<detail::GetDefaultHandleType<FromU>, FromT> &&
0139 detail::isDefaultHandleType<FromU>,
0140 int> = 0>
0141 void setFrom(FromU value) {
0142 m_obj->m_from = std::make_unique<detail::GetDefaultHandleType<FromU>>(value);
0143 }
0144
0145
0146
0147
0148
0149
0150 template <typename FromU,
0151 std::enable_if_t<Mutable && std::is_same_v<detail::GetMutableHandleType<FromT>, FromU> &&
0152 detail::isMutableHandleType<FromU>,
0153 int> = 0>
0154 void setFrom(FromU value) {
0155 setFrom(detail::GetDefaultHandleType<FromU>(value));
0156 }
0157
0158
0159
0160
0161
0162
0163 template <typename FromU, std::enable_if_t<Mutable && detail::isInterfaceInitializableFrom<FromT, FromU>, int> = 0>
0164 void setFrom(FromU value) {
0165 setFrom(FromT(value));
0166 }
0167
0168
0169 const ToT getTo() const {
0170 if (!m_obj->m_to) {
0171 return ToT::makeEmpty();
0172 }
0173 return ToT(*(m_obj->m_to));
0174 }
0175
0176
0177
0178
0179
0180
0181 template <typename ToU,
0182 std::enable_if_t<Mutable && std::is_same_v<detail::GetDefaultHandleType<ToU>, ToT> &&
0183 detail::isDefaultHandleType<ToU>,
0184 int> = 0>
0185 void setTo(ToU value) {
0186 m_obj->m_to = std::make_unique<detail::GetDefaultHandleType<ToU>>(value);
0187 }
0188
0189
0190
0191
0192
0193
0194 template <typename ToU,
0195 std::enable_if_t<Mutable && std::is_same_v<detail::GetMutableHandleType<ToT>, ToU> &&
0196 detail::isMutableHandleType<ToU>,
0197 int> = 0>
0198 void setTo(ToU value) {
0199 setTo(detail::GetDefaultHandleType<ToU>(value));
0200 }
0201
0202
0203
0204
0205
0206
0207 template <typename ToU, std::enable_if_t<Mutable && detail::isInterfaceInitializableFrom<ToT, ToU>, int> = 0>
0208 void setTo(ToU value) {
0209 setTo(ToT(value));
0210 }
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220 template <typename T, typename = std::enable_if_t<!std::is_same_v<ToT, FromT> && isFromOrToT<T>>>
0221 T get() const {
0222 if constexpr (std::is_same_v<T, FromT>) {
0223 return getFrom();
0224 } else {
0225 return getTo();
0226 }
0227 }
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238 template <size_t Index, typename = std::enable_if_t<(Index < 3)>>
0239 auto get() const {
0240 if constexpr (Index == 0) {
0241 return getFrom();
0242 } else if constexpr (Index == 1) {
0243 return getTo();
0244 } else {
0245 return getWeight();
0246 }
0247 }
0248
0249
0250
0251
0252
0253
0254
0255
0256 template <typename T,
0257 std::enable_if_t<Mutable && !std::is_same_v<ToT, FromT> &&
0258 (isMutableFromOrToT<T> || detail::isInterfaceInitializableFrom<ToT, T> ||
0259 detail::isInterfaceInitializableFrom<FromT, T>),
0260 int> = 0>
0261 void set(T value) {
0262 if constexpr (std::is_same_v<T, FromT>) {
0263 setFrom(std::move(value));
0264 } else {
0265 setTo(std::move(value));
0266 }
0267 }
0268
0269
0270 bool isAvailable() const {
0271 return m_obj;
0272 }
0273
0274
0275 void unlink() {
0276 m_obj = podio::utils::MaybeSharedPtr<LinkObjT>(nullptr);
0277 }
0278
0279
0280 podio::ObjectID getObjectID() const {
0281 if (m_obj) {
0282 return m_obj->id;
0283 }
0284 return podio::ObjectID{};
0285 }
0286
0287 podio::ObjectID id() const {
0288 return getObjectID();
0289 }
0290
0291 bool operator==(const LinkT& other) const {
0292 return m_obj == other.m_obj;
0293 }
0294
0295 bool operator!=(const LinkT& other) const {
0296 return !(*this == other);
0297 }
0298
0299 template <typename FromU, typename ToU, typename = std::enable_if_t<sameTypes<FromU, ToU>>>
0300 bool operator==(const LinkT<FromU, ToU, !Mutable>& other) const {
0301 return m_obj == other.m_obj;
0302 }
0303
0304 template <typename FromU, typename ToU, typename = std::enable_if_t<sameTypes<FromU, ToU>>>
0305 bool operator!=(const LinkT<FromU, ToU, !Mutable>& other) const {
0306 return !(*this == other);
0307 }
0308
0309 bool operator<(const LinkT& other) const {
0310 return m_obj < other.m_obj;
0311 }
0312
0313 friend void swap(LinkT& a, LinkT& b) {
0314 using std::swap;
0315 swap(a.m_obj, b.m_obj);
0316 }
0317
0318 private:
0319
0320 explicit LinkT(podio::utils::MaybeSharedPtr<LinkObjT> obj) : m_obj(std::move(obj)) {
0321 }
0322
0323 template <bool Mut = Mutable, typename = std::enable_if_t<!Mut && !Mutable>>
0324 LinkT(LinkObjT* obj) : m_obj(podio::utils::MaybeSharedPtr<LinkObjT>(obj)) {
0325 }
0326
0327 podio::utils::MaybeSharedPtr<LinkObjT> m_obj{nullptr};
0328 };
0329
0330 template <typename FromT, typename ToT>
0331 std::ostream& operator<<(std::ostream& os, const Link<FromT, ToT>& link) {
0332 if (!link.isAvailable()) {
0333 return os << "[not available]";
0334 }
0335
0336 return os << " id: " << link.id() << '\n'
0337 << " weight: " << link.getWeight() << '\n'
0338 << " from: " << link.getFrom().id() << '\n'
0339 << " to: " << link.getTo().id() << '\n';
0340 }
0341
0342 #if defined(PODIO_JSON_OUTPUT) && !defined(__CLING__)
0343 template <typename FromT, typename ToT>
0344 void to_json(nlohmann::json& j, const podio::LinkT<FromT, ToT, false>& link) {
0345 j = nlohmann::json{{"weight", link.getWeight()}};
0346
0347 j["from"] = nlohmann::json{{"collectionID", link.getFrom().getObjectID().collectionID},
0348 {"index", link.getFrom().getObjectID().index}};
0349
0350 j["to"] = nlohmann::json{{"collectionID", link.getTo().getObjectID().collectionID},
0351 {"index", link.getTo().getObjectID().index}};
0352 }
0353 #endif
0354
0355 }
0356
0357 #endif