File indexing completed on 2023-10-25 09:38:44
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 REF castTo() const;
0103
0104 bool isNull() const;
0105 bool isNonnull() const;
0106 bool operator!() const;
0107
0108 bool operator==(RefToBase const& rhs) const;
0109 bool operator!=(RefToBase const& rhs) const;
0110
0111 void swap(RefToBase& other);
0112
0113 std::unique_ptr<reftobase::RefHolderBase> holder() const;
0114
0115 EDProductGetter const* productGetter() const;
0116
0117
0118
0119
0120
0121 bool isAvailable() const { return holder_ ? holder_->isAvailable() : false; }
0122
0123 bool isTransient() const { return holder_ ? holder_->isTransient() : false; }
0124
0125
0126 CMS_CLASS_VERSION(10)
0127 private:
0128 value_type const* getPtrImpl() const;
0129 reftobase::BaseHolder<value_type>* holder_;
0130 friend class RefToBaseVector<T>;
0131 friend class RefToBaseProd<T>;
0132 template <typename B>
0133 friend class RefToBase;
0134 };
0135
0136
0137
0138
0139
0140 template <class T>
0141 inline RefToBase<T>::RefToBase() : holder_(nullptr) {}
0142
0143 template <class T>
0144 inline RefToBase<T>::RefToBase(RefToBase const& other) : holder_(other.holder_ ? other.holder_->clone() : nullptr) {}
0145
0146 template <class T>
0147 inline RefToBase<T>::RefToBase(RefToBase&& other) noexcept : holder_(other.holder_) {
0148 other.holder_ = nullptr;
0149 }
0150
0151 template <class T>
0152 inline RefToBase<T>& RefToBase<T>::operator=(RefToBase&& other) noexcept {
0153 delete holder_;
0154 holder_ = other.holder_;
0155 other.holder_ = nullptr;
0156 return *this;
0157 }
0158
0159 template <class T>
0160 template <typename C1, typename T1, typename F1>
0161 inline RefToBase<T>::RefToBase(Ref<C1, T1, F1> const& iRef)
0162 : holder_(new reftobase::Holder<T, Ref<C1, T1, F1>>(iRef)) {}
0163
0164 template <class T>
0165 template <typename C>
0166 inline RefToBase<T>::RefToBase(RefProd<C> const& iRef) : holder_(new reftobase::Holder<T, RefProd<C>>(iRef)) {}
0167
0168 template <class T>
0169 template <typename T1>
0170 inline RefToBase<T>::RefToBase(RefToBase<T1> const& iRef)
0171 : holder_(
0172 new reftobase::IndirectHolder<T>(std::shared_ptr<edm::reftobase::RefHolderBase>(iRef.holder().release()))) {
0173
0174
0175
0176
0177
0178 static_assert(std::is_base_of<T, T1>::value, "RefToBase::RefToBase T not base of T1");
0179 }
0180
0181 template <class T>
0182 inline RefToBase<T>::RefToBase(std::unique_ptr<reftobase::BaseHolder<value_type>> p) : holder_(p.release()) {}
0183
0184 template <class T>
0185 inline RefToBase<T>::RefToBase(std::shared_ptr<reftobase::RefHolderBase> p)
0186 : holder_(new reftobase::IndirectHolder<T>(p)) {}
0187
0188 template <class T>
0189 inline RefToBase<T>::~RefToBase() noexcept {
0190 delete holder_;
0191 }
0192
0193 template <class T>
0194 inline RefToBase<T>& RefToBase<T>::operator=(RefToBase<T> const& iRHS) {
0195 RefToBase<T> temp(iRHS);
0196 temp.swap(*this);
0197 return *this;
0198 }
0199
0200 template <class T>
0201 inline T const& RefToBase<T>::operator*() const {
0202 return *getPtrImpl();
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>::get() const {
0212 return getPtrImpl();
0213 }
0214
0215 template <class T>
0216 inline ProductID RefToBase<T>::id() const {
0217 return holder_ ? holder_->id() : ProductID();
0218 }
0219
0220 template <class T>
0221 inline size_t RefToBase<T>::key() const {
0222 if (holder_ == nullptr) {
0223 Exception::throwThis(errors::InvalidReference,
0224 "attempting get key from null RefToBase;\n"
0225 "You should check for nullity before calling key().");
0226 return 0;
0227 }
0228 return holder_->key();
0229 }
0230
0231 namespace {
0232
0233
0234 template <typename T, typename U>
0235 typename std::enable_if<std::is_class<T>::value>::type checkTypeCompatibility() {
0236 static_assert(std::is_base_of<T, U>::value || std::is_base_of<U, T>::value,
0237 "RefToBase::castTo error element types are not related by inheritance");
0238 }
0239
0240 template <typename T, typename U>
0241 typename std::enable_if<!std::is_class<T>::value>::type checkTypeCompatibility() {
0242 static_assert(std::is_same<T, U>::value, "RefToBase::castTo error non-class element types are not the same");
0243 }
0244
0245
0246 template <typename T, typename OUT>
0247 typename std::enable_if<std::is_class<T>::value, OUT const*>::type convertTo(T const* t) {
0248 return dynamic_cast<OUT const*>(t);
0249 }
0250
0251 template <typename T, typename OUT>
0252 typename std::enable_if<!std::is_class<T>::value, OUT const*>::type convertTo(T const* t) {
0253 return t;
0254 }
0255 }
0256
0257 template <class T>
0258 template <class REF>
0259 REF RefToBase<T>::castTo() const {
0260 if (!holder_) {
0261 Exception::throwThis(errors::InvalidReference,
0262 "attempting to cast a null RefToBase;\n"
0263 "You should check for nullity before casting.");
0264 }
0265
0266 checkTypeCompatibility<T, typename REF::value_type>();
0267
0268
0269
0270
0271
0272 EDProductGetter const* getter = productGetter();
0273 if (getter) {
0274 return REF(id(), key(), getter);
0275 }
0276
0277 T const* value = get();
0278 if (value == nullptr) {
0279 return REF(id());
0280 }
0281 typename REF::value_type const* newValue = convertTo<T, typename REF::value_type>(value);
0282 if (newValue) {
0283 return REF(id(), newValue, key(), isTransient());
0284 }
0285
0286 Exception::throwThis(errors::InvalidReference,
0287 "RefToBase<T>::castTo Error attempting to cast mismatched types\n"
0288 "casting from RefToBase with T: ",
0289 typeid(T).name(),
0290 "\ncasting to: ",
0291 typeid(REF).name());
0292 return REF();
0293 }
0294
0295
0296 template <class T>
0297 inline bool RefToBase<T>::isNull() const {
0298 return !id().isValid();
0299 }
0300
0301
0302 template <class T>
0303 inline bool RefToBase<T>::isNonnull() const {
0304 return !isNull();
0305 }
0306
0307
0308 template <class T>
0309 inline bool RefToBase<T>::operator!() const {
0310 return isNull();
0311 }
0312
0313 template <class T>
0314 inline bool RefToBase<T>::operator==(RefToBase<T> const& rhs) const {
0315 return holder_ ? holder_->isEqualTo(*rhs.holder_) : holder_ == rhs.holder_;
0316 }
0317
0318 template <class T>
0319 inline bool RefToBase<T>::operator!=(RefToBase<T> const& rhs) const {
0320 return !(*this == rhs);
0321 }
0322
0323 template <class T>
0324 inline void RefToBase<T>::swap(RefToBase<T>& other) {
0325 std::swap(holder_, other.holder_);
0326 }
0327
0328 template <class T>
0329 inline EDProductGetter const* RefToBase<T>::productGetter() const {
0330 return holder_ ? holder_->productGetter() : nullptr;
0331 }
0332
0333 template <class T>
0334 inline T const* RefToBase<T>::getPtrImpl() const {
0335 return holder_ ? holder_->getPtr() : nullptr;
0336 }
0337
0338 template <class T>
0339 std::unique_ptr<reftobase::RefHolderBase> RefToBase<T>::holder() const {
0340 return holder_ ? holder_->holder() : std::unique_ptr<reftobase::RefHolderBase>();
0341 }
0342
0343
0344 template <class T>
0345 inline void swap(RefToBase<T>& a, RefToBase<T>& b) {
0346 a.swap(b);
0347 }
0348 }
0349
0350 #include "DataFormats/Common/interface/RefToBaseProd.h"
0351 #include "DataFormats/Common/interface/Handle.h"
0352 #include "DataFormats/Common/interface/View.h"
0353
0354 namespace edm {
0355 template <class T>
0356 inline RefToBase<T>::RefToBase(RefToBaseProd<T> const& r, size_t i)
0357 : holder_(r.operator->()->refAt(i).holder_->clone()) {}
0358
0359 template <typename T>
0360 inline RefToBase<T>::RefToBase(Handle<View<T>> const& handle, size_t i)
0361 : holder_(handle.operator->()->refAt(i).holder_->clone()) {}
0362
0363 }
0364
0365 #endif