00001 #ifndef DataFormats_Common_Ptr_h
00002 #define DataFormats_Common_Ptr_h
00003
00004
00005
00006
00007
00016
00017
00018
00019
00020
00021
00022 #include "boost/type_traits/is_base_of.hpp"
00023 #include "boost/utility/enable_if.hpp"
00024
00025
00026 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
00027 #include "DataFormats/Common/interface/RefCore.h"
00028 #include "DataFormats/Common/interface/traits.h"
00029 #include "DataFormats/Common/interface/GetProduct.h"
00030 #include "DataFormats/Common/interface/EDProduct.h"
00031 #include "DataFormats/Common/interface/EDProductGetter.h"
00032 #include "DataFormats/Common/interface/Handle.h"
00033 #include "DataFormats/Common/interface/OrphanHandle.h"
00034 #include "DataFormats/Common/interface/TestHandle.h"
00035
00036
00037 namespace edm {
00038 template <typename T>
00039 class Ptr {
00040 friend class PtrVectorBase;
00041 public:
00042
00043 typedef unsigned long key_type;
00044 typedef T value_type;
00045
00046
00047 template <typename C>
00048 Ptr(Handle<C> const& handle, key_type itemKey, bool setNow=true):
00049 core_(handle.id(), getItem_(handle.product(), itemKey), 0, false), key_(itemKey) {}
00050
00051
00052 template <typename C>
00053 Ptr(OrphanHandle<C> const& handle, key_type itemKey, bool setNow=true):
00054 core_(handle.id(), getItem_(handle.product(), itemKey), 0, false), key_(itemKey) {}
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 template <typename C>
00068 Ptr(C const* product, key_type itemKey, bool setNow=true):
00069 core_(ProductID(), product != 0 ? getItem_(product,itemKey) : 0, 0, true),
00070 key_(product != 0 ? itemKey : key_traits<key_type>::value) {}
00071
00072
00073
00074
00075 template <typename C>
00076 Ptr(TestHandle<C> const& handle, key_type itemKey, bool setNow=true):
00077 core_(handle.id(), getItem_(handle.product(), itemKey), 0, true), key_(itemKey) {}
00078
00082 Ptr(ProductID const& productID, key_type itemKey, EDProductGetter const* prodGetter) :
00083 core_(productID, 0, mustBeNonZero(prodGetter, "Ptr", productID), false), key_(itemKey) {
00084 }
00085
00093 Ptr(ProductID const& productID, T const* item, key_type item_key) :
00094 core_(productID, item, 0, false),
00095 key_(item_key) {
00096 }
00097
00102 explicit Ptr(ProductID const& id) :
00103 core_(id, 0, 0, false),
00104 key_(key_traits<key_type>::value)
00105 { }
00106
00107 Ptr():
00108 core_(),
00109 key_(key_traits<key_type>::value)
00110 {}
00111
00112 Ptr(Ptr<T> const& iOther):
00113 core_(iOther.core_),
00114 key_(iOther.key_)
00115 {}
00116
00117 template<typename U>
00118 Ptr(Ptr<U> const& iOther, typename boost::enable_if_c<boost::is_base_of<T, U>::value>::type * = 0):
00119 core_(iOther.id(),
00120 (iOther.hasProductCache() ? static_cast<T const*>(iOther.get()): static_cast<T const*>(0)),
00121 iOther.productGetter(),
00122 iOther.isTransient()),
00123 key_(iOther.key()) {
00124 }
00125
00126 template<typename U>
00127 explicit
00128 Ptr(Ptr<U> const& iOther, typename boost::enable_if_c<boost::is_base_of<U, T>::value>::type * = 0):
00129 core_(iOther.id(),
00130 dynamic_cast<T const*>(iOther.get()),
00131 0,
00132 iOther.isTransient()),
00133 key_(iOther.key()) {
00134 }
00135
00137 ~Ptr() {}
00138
00140 T const&
00141 operator*() const;
00142
00144 T const*
00145 operator->() const;
00146
00148 T const* get() const {
00149 return isNull() ? 0 : this->operator->();
00150 }
00151
00153 bool isNull() const {return !isNonnull(); }
00154
00156
00157 bool isNonnull() const {return key_traits<key_type>::value != key_;}
00159 bool operator!() const {return isNull();}
00160
00163 bool isAvailable() const {return core_.isAvailable();}
00164
00166 bool isTransient() const {return core_.isTransient();}
00167
00169 ProductID id() const {return core_.id();}
00170
00172 EDProductGetter const* productGetter() const {return core_.productGetter();}
00173
00174 key_type key() const {return key_;}
00175
00176 bool hasProductCache() const { return 0 != core_.productPtr(); }
00177
00178 RefCore const& refCore() const {return core_;}
00179
00180
00181 void const* product() const {return 0;}
00182
00183
00184 CMS_CLASS_VERSION(10)
00185
00186 private:
00187
00188
00190 Ptr(T const* item, key_type item_key) :
00191 core_(ProductID(), item, 0, true),
00192 key_(item_key) {
00193 }
00194
00195
00196 template<typename C>
00197 T const* getItem_(C const* product, key_type iKey);
00198
00199 void getData_() const {
00200 if(!hasProductCache() && 0 != productGetter()) {
00201 void const* ad = 0;
00202 EDProduct const* prod = productGetter()->getIt(core_.id());
00203 if(prod == 0) {
00204 core_.productNotFoundException(typeid(T));
00205 }
00206 prod->setPtr(typeid(T), key_, ad);
00207 core_.setProductPtr(ad);
00208 }
00209 }
00210
00211 RefCore core_;
00212 key_type key_;
00213 };
00214
00215 template<typename T>
00216 template<typename C>
00217 T const* Ptr<T>::getItem_(C const* product, key_type iKey) {
00218 assert (product != 0);
00219 typename C::const_iterator it = product->begin();
00220 std::advance(it,iKey);
00221 T const* address = detail::GetProduct<C>::address(it);
00222 return address;
00223 }
00224
00226 template <typename T>
00227 inline
00228 T const&
00229 Ptr<T>::operator*() const {
00230 getData_();
00231 return *reinterpret_cast<T const*>(core_.productPtr());
00232 }
00233
00235 template <typename T>
00236 inline
00237 T const*
00238 Ptr<T>::operator->() const {
00239 getData_();
00240 return reinterpret_cast<T const*>(core_.productPtr());
00241 }
00242
00243 template <typename T>
00244 inline
00245 bool
00246 operator==(Ptr<T> const& lhs, Ptr<T> const& rhs) {
00247 return lhs.refCore() == rhs.refCore() && lhs.key() == rhs.key();
00248 }
00249
00250 template <typename T>
00251 inline
00252 bool
00253 operator!=(Ptr<T> const& lhs, Ptr<T> const& rhs) {
00254 return !(lhs == rhs);
00255 }
00256
00257 template <typename T>
00258 inline
00259 bool
00260 operator<(Ptr<T> const& lhs, Ptr<T> const& rhs) {
00263 return (lhs.refCore() == rhs.refCore() ? lhs.key() < rhs.key() : lhs.refCore() < rhs.refCore());
00264 }
00265
00266 }
00267
00268 #endif