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