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