File indexing completed on 2024-08-24 09:50:39
0001 #ifndef DataFormats_Common_RefToBase_h
0002 #define DataFormats_Common_RefToBase_h
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
0038 #include "DataFormats/Common/interface/EDProductfwd.h"
0039 #include "FWCore/Utilities/interface/EDMException.h"
0040 #include "DataFormats/Common/interface/BaseHolder.h"
0041
0042 #include "DataFormats/Common/interface/Holder.h"
0043 #include "DataFormats/Common/interface/IndirectHolder.h"
0044 #include "DataFormats/Common/interface/RefHolder.h"
0045
0046 #include <memory>
0047 #include <type_traits>
0048
0049 namespace edm {
0050
0051
0052
0053
0054
0055
0056
0057
0058 template <typename T>
0059 class RefToBaseVector;
0060 template <typename C, typename T, typename F>
0061 class Ref;
0062 template <typename C>
0063 class RefProd;
0064 template <typename T>
0065 class RefToBaseProd;
0066 template <typename T>
0067 class View;
0068
0069 template <class T>
0070 class RefToBase {
0071 public:
0072 typedef T value_type;
0073
0074 RefToBase();
0075 RefToBase(RefToBase const& other);
0076 RefToBase(RefToBase&& other) noexcept;
0077 RefToBase& operator=(RefToBase&& other) noexcept;
0078
0079 template <typename C1, typename T1, typename F1>
0080 explicit RefToBase(Ref<C1, T1, F1> const& r);
0081 template <typename C>
0082 explicit RefToBase(RefProd<C> const& r);
0083 RefToBase(RefToBaseProd<T> const& r, size_t i);
0084 RefToBase(Handle<View<T>> const& handle, size_t i);
0085 template <typename T1>
0086 explicit RefToBase(RefToBase<T1> const& r);
0087 RefToBase(std::unique_ptr<reftobase::BaseHolder<value_type>>);
0088 RefToBase(std::shared_ptr<reftobase::RefHolderBase> p);
0089
0090 ~RefToBase() noexcept;
0091
0092 RefToBase& operator=(RefToBase const& rhs);
0093
0094 value_type const& operator*() const;
0095 value_type const* operator->() const;
0096 value_type const* get() const;
0097
0098 ProductID id() const;
0099 size_t key() const;
0100
0101 template <class REF>
0102 requires requires {
0103 typename REF::value_type;
0104 requires std::is_same_v<T, typename REF::value_type> or std::is_base_of_v<T, typename REF::value_type> or
0105 std::is_base_of_v<typename REF::value_type, T>;
0106 }
0107 REF castTo() const;
0108
0109 bool isNull() const;
0110 bool isNonnull() const;
0111 bool operator!() const;
0112
0113 bool operator==(RefToBase const& rhs) const;
0114 bool operator!=(RefToBase const& rhs) const;
0115
0116 void swap(RefToBase& other);
0117
0118 std::unique_ptr<reftobase::RefHolderBase> holder() const;
0119
0120 EDProductGetter const* productGetter() const;
0121
0122
0123
0124
0125
0126 bool isAvailable() const { return holder_ ? holder_->isAvailable() : false; }
0127
0128 bool isTransient() const { return holder_ ? holder_->isTransient() : false; }
0129
0130
0131 CMS_CLASS_VERSION(10)
0132 private:
0133 value_type const* getPtrImpl() const;
0134 reftobase::BaseHolder<value_type>* holder_;
0135 friend class RefToBaseVector<T>;
0136 friend class RefToBaseProd<T>;
0137 template <typename B>
0138 friend class RefToBase;
0139 };
0140
0141
0142
0143
0144
0145 template <class T>
0146 inline RefToBase<T>::RefToBase() : holder_(nullptr) {}
0147
0148 template <class T>
0149 inline RefToBase<T>::RefToBase(RefToBase const& other) : holder_(other.holder_ ? other.holder_->clone() : nullptr) {}
0150
0151 template <class T>
0152 inline RefToBase<T>::RefToBase(RefToBase&& other) noexcept : holder_(other.holder_) {
0153 other.holder_ = nullptr;
0154 }
0155
0156 template <class T>
0157 inline RefToBase<T>& RefToBase<T>::operator=(RefToBase&& other) noexcept {
0158 delete holder_;
0159 holder_ = other.holder_;
0160 other.holder_ = nullptr;
0161 return *this;
0162 }
0163
0164 template <class T>
0165 template <typename C1, typename T1, typename F1>
0166 inline RefToBase<T>::RefToBase(Ref<C1, T1, F1> const& iRef)
0167 : holder_(new reftobase::Holder<T, Ref<C1, T1, F1>>(iRef)) {}
0168
0169 template <class T>
0170 template <typename C>
0171 inline RefToBase<T>::RefToBase(RefProd<C> const& iRef) : holder_(new reftobase::Holder<T, RefProd<C>>(iRef)) {}
0172
0173 template <class T>
0174 template <typename T1>
0175 inline RefToBase<T>::RefToBase(RefToBase<T1> const& iRef)
0176 : holder_(
0177 new reftobase::IndirectHolder<T>(std::shared_ptr<edm::reftobase::RefHolderBase>(iRef.holder().release()))) {
0178
0179
0180
0181
0182
0183 static_assert(std::is_base_of<T, T1>::value, "RefToBase::RefToBase T not base of T1");
0184 }
0185
0186 template <class T>
0187 inline RefToBase<T>::RefToBase(std::unique_ptr<reftobase::BaseHolder<value_type>> p) : holder_(p.release()) {}
0188
0189 template <class T>
0190 inline RefToBase<T>::RefToBase(std::shared_ptr<reftobase::RefHolderBase> p)
0191 : holder_(new reftobase::IndirectHolder<T>(p)) {}
0192
0193 template <class T>
0194 inline RefToBase<T>::~RefToBase() noexcept {
0195 delete holder_;
0196 }
0197
0198 template <class T>
0199 inline RefToBase<T>& RefToBase<T>::operator=(RefToBase<T> const& iRHS) {
0200 RefToBase<T> temp(iRHS);
0201 temp.swap(*this);
0202 return *this;
0203 }
0204
0205 template <class T>
0206 inline T const& RefToBase<T>::operator*() const {
0207 return *getPtrImpl();
0208 }
0209
0210 template <class T>
0211 inline T const* RefToBase<T>::operator->() const {
0212 return getPtrImpl();
0213 }
0214
0215 template <class T>
0216 inline T const* RefToBase<T>::get() const {
0217 return getPtrImpl();
0218 }
0219
0220 template <class T>
0221 inline ProductID RefToBase<T>::id() const {
0222 return holder_ ? holder_->id() : ProductID();
0223 }
0224
0225 template <class T>
0226 inline size_t RefToBase<T>::key() const {
0227 if (holder_ == nullptr) {
0228 Exception::throwThis(errors::InvalidReference,
0229 "attempting get key from null RefToBase;\n"
0230 "You should check for nullity before calling key().");
0231 return 0;
0232 }
0233 return holder_->key();
0234 }
0235
0236 template <class T>
0237 template <class REF>
0238 requires requires {
0239 typename REF::value_type;
0240 requires std::is_same_v<T, typename REF::value_type> or std::is_base_of_v<T, typename REF::value_type> or
0241 std::is_base_of_v<typename REF::value_type, T>;
0242 }
0243 REF RefToBase<T>::castTo() const {
0244 if (!holder_) {
0245 Exception::throwThis(errors::InvalidReference,
0246 "attempting to cast a null RefToBase;\n"
0247 "You should check for nullity before casting.");
0248 }
0249
0250
0251
0252
0253
0254 EDProductGetter const* getter = productGetter();
0255 if (getter) {
0256 return REF(id(), key(), getter);
0257 }
0258
0259 T const* value = get();
0260 if (value == nullptr) {
0261 return REF(id());
0262 }
0263 typename REF::value_type const* newValue;
0264 if constexpr (std::is_same_v<T, typename REF::value_type> or std::is_base_of_v<typename REF::value_type, T>) {
0265 newValue = value;
0266 } else {
0267 newValue = dynamic_cast<typename REF::value_type const*>(value);
0268 }
0269 if (newValue) {
0270 return REF(id(), newValue, key(), isTransient());
0271 }
0272
0273 Exception::throwThis(errors::InvalidReference,
0274 "RefToBase<T>::castTo Error attempting to cast mismatched types\n"
0275 "casting from RefToBase with T: ",
0276 typeid(T).name(),
0277 "\ncasting to: ",
0278 typeid(REF).name());
0279 return REF();
0280 }
0281
0282
0283 template <class T>
0284 inline bool RefToBase<T>::isNull() const {
0285 return !id().isValid();
0286 }
0287
0288
0289 template <class T>
0290 inline bool RefToBase<T>::isNonnull() const {
0291 return !isNull();
0292 }
0293
0294
0295 template <class T>
0296 inline bool RefToBase<T>::operator!() const {
0297 return isNull();
0298 }
0299
0300 template <class T>
0301 inline bool RefToBase<T>::operator==(RefToBase<T> const& rhs) const {
0302 return holder_ ? holder_->isEqualTo(*rhs.holder_) : holder_ == rhs.holder_;
0303 }
0304
0305 template <class T>
0306 inline bool RefToBase<T>::operator!=(RefToBase<T> const& rhs) const {
0307 return !(*this == rhs);
0308 }
0309
0310 template <class T>
0311 inline void RefToBase<T>::swap(RefToBase<T>& other) {
0312 std::swap(holder_, other.holder_);
0313 }
0314
0315 template <class T>
0316 inline EDProductGetter const* RefToBase<T>::productGetter() const {
0317 return holder_ ? holder_->productGetter() : nullptr;
0318 }
0319
0320 template <class T>
0321 inline T const* RefToBase<T>::getPtrImpl() const {
0322 return holder_ ? holder_->getPtr() : nullptr;
0323 }
0324
0325 template <class T>
0326 std::unique_ptr<reftobase::RefHolderBase> RefToBase<T>::holder() const {
0327 return holder_ ? holder_->holder() : std::unique_ptr<reftobase::RefHolderBase>();
0328 }
0329
0330
0331 template <class T>
0332 inline void swap(RefToBase<T>& a, RefToBase<T>& b) {
0333 a.swap(b);
0334 }
0335 }
0336
0337 #include "DataFormats/Common/interface/RefToBaseProd.h"
0338 #include "DataFormats/Common/interface/Handle.h"
0339 #include "DataFormats/Common/interface/View.h"
0340
0341 namespace edm {
0342 template <class T>
0343 inline RefToBase<T>::RefToBase(RefToBaseProd<T> const& r, size_t i)
0344 : holder_(r.operator->()->refAt(i).holder_->clone()) {}
0345
0346 template <typename T>
0347 inline RefToBase<T>::RefToBase(Handle<View<T>> const& handle, size_t i)
0348 : holder_(handle.operator->()->refAt(i).holder_->clone()) {}
0349
0350 }
0351
0352 #endif