00001 #ifndef DataFormats_Common_RefHolder__h 00002 #define DataFormats_Common_RefHolder__h 00003 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h" 00004 00005 #include "DataFormats/Common/interface/RefHolderBase.h" 00006 #include "DataFormats/Provenance/interface/ProductID.h" 00007 #include "Reflex/Object.h" 00008 #include "Reflex/Type.h" 00009 #include "FWCore/Utilities/interface/UseReflex.h" 00010 #include <memory> 00011 00012 namespace edm { 00013 namespace reftobase { 00014 //------------------------------------------------------------------ 00015 // Class template RefHolder<REF> 00016 //------------------------------------------------------------------ 00017 00018 00019 template <class REF> 00020 class RefHolder : public RefHolderBase { 00021 public: 00022 RefHolder(); 00023 explicit RefHolder(REF const& ref); 00024 RefHolder(RefHolder const& other); 00025 RefHolder& operator=(RefHolder const& rhs); 00026 void swap(RefHolder& other); 00027 virtual ~RefHolder(); 00028 virtual RefHolderBase* clone() const; 00029 00030 virtual ProductID id() const; 00031 virtual size_t key() const; 00032 virtual bool isEqualTo(RefHolderBase const& rhs) const; 00033 virtual bool fillRefIfMyTypeMatches(RefHolderBase& fillme, 00034 std::string& msg) const; 00035 REF const& getRef() const; 00036 void setRef(REF const& r); 00037 virtual std::auto_ptr<RefVectorHolderBase> makeVectorHolder() const; 00038 virtual EDProductGetter const* productGetter() const; 00039 virtual bool hasProductCache() const; 00040 virtual void const * product() const; 00041 00044 virtual bool isAvailable() const { return ref_.isAvailable(); } 00045 00046 //Needed for ROOT storage 00047 CMS_CLASS_VERSION(10) 00048 private: 00049 virtual void const* pointerToType(Reflex::Type const& iToType) const; 00050 REF ref_; 00051 }; 00052 00053 //------------------------------------------------------------------ 00054 // Implementation of RefHolder<REF> 00055 //------------------------------------------------------------------ 00056 00057 template <class REF> 00058 RefHolder<REF>::RefHolder() : 00059 RefHolderBase(), ref_() 00060 { } 00061 00062 template <class REF> 00063 RefHolder<REF>::RefHolder(RefHolder const& rhs) : 00064 RefHolderBase(rhs), ref_( rhs.ref_ ) 00065 { } 00066 00067 template <class REF> 00068 RefHolder<REF>& RefHolder<REF>::operator=(RefHolder const& rhs) { 00069 ref_ = rhs.ref_; return *this; 00070 } 00071 00072 template <class REF> 00073 RefHolder<REF>::RefHolder(REF const& ref) : 00074 RefHolderBase(), ref_(ref) 00075 { } 00076 00077 template <class REF> 00078 RefHolder<REF>::~RefHolder() 00079 { } 00080 00081 template <class REF> 00082 RefHolderBase* 00083 RefHolder<REF>::clone() const 00084 { 00085 return new RefHolder(ref_); 00086 } 00087 00088 template <class REF> 00089 ProductID 00090 RefHolder<REF>::id() const 00091 { 00092 return ref_.id(); 00093 } 00094 00095 template <class REF> 00096 bool 00097 RefHolder<REF>::isEqualTo(RefHolderBase const& rhs) const 00098 { 00099 RefHolder const* h(dynamic_cast<RefHolder const*>(&rhs)); 00100 return h && (getRef() == h->getRef()); 00101 } 00102 00103 template <class REF> 00104 bool 00105 RefHolder<REF>::fillRefIfMyTypeMatches(RefHolderBase& fillme, 00106 std::string& msg) const 00107 { 00108 RefHolder* h = dynamic_cast<RefHolder*>(&fillme); 00109 bool conversion_worked = (h != 0); 00110 if (conversion_worked) 00111 h->setRef(ref_); 00112 else 00113 msg = typeid(REF).name(); 00114 return conversion_worked; 00115 } 00116 00117 template <class REF> 00118 inline 00119 REF const& 00120 RefHolder<REF>::getRef() const 00121 { 00122 return ref_; 00123 } 00124 00125 template<class REF> 00126 EDProductGetter const* RefHolder<REF>::productGetter() const { 00127 return ref_.productGetter(); 00128 } 00129 00130 template<class REF> 00131 bool RefHolder<REF>::hasProductCache() const { 00132 return ref_.hasProductCache(); 00133 } 00134 00135 template<class REF> 00136 void const * RefHolder<REF>::product() const { 00137 return ref_.product(); 00138 } 00139 00140 template <class REF> 00141 inline 00142 void 00143 RefHolder<REF>::swap(RefHolder& other) 00144 { 00145 std::swap(ref_, other.ref_); 00146 } 00147 00148 template <class REF> 00149 inline 00150 void 00151 RefHolder<REF>::setRef(REF const& r) 00152 { 00153 ref_ = r; 00154 } 00155 00156 template <class REF> 00157 void const* 00158 RefHolder<REF>::pointerToType(Reflex::Type const& iToType) const 00159 { 00160 typedef typename REF::value_type contained_type; 00161 static const Reflex::Type s_type(Reflex::Type::ByTypeInfo(typeid(contained_type))); 00162 00163 // The const_cast below is needed because 00164 // Object's constructor requires a pointer to 00165 // non-const void, although the implementation does not, of 00166 // course, modify the object to which the pointer points. 00167 Reflex::Object obj(s_type, const_cast<void*>(static_cast<const void*>(ref_.get()))); 00168 if ( s_type == iToType ) return obj.Address(); 00169 Reflex::Object cast = obj.CastObject(iToType); 00170 return cast.Address(); // returns void*, after pointer adjustment 00171 } 00172 } // namespace reftobase 00173 } 00174 00175 #endif