00001 #ifndef DataFormats_Common_IndirectVectorHolder_h 00002 #define DataFormats_Common_IndirectVectorHolder_h 00003 #include "DataFormats/Common/interface/BaseVectorHolder.h" 00004 #include "DataFormats/Common/interface/RefVectorHolderBase.h" 00005 #include "DataFormats/Common/interface/IndirectHolder.h" 00006 #include <memory> 00007 00008 namespace edm { 00009 namespace reftobase { 00010 00011 template <typename T> 00012 class IndirectVectorHolder : public BaseVectorHolder<T> { 00013 public: 00014 typedef BaseVectorHolder<T> base_type; 00015 typedef typename base_type::size_type size_type; 00016 typedef typename base_type::element_type element_type; 00017 typedef typename base_type::base_ref_type base_ref_type; 00018 typedef typename base_type::const_iterator const_iterator; 00019 00020 IndirectVectorHolder(); 00021 IndirectVectorHolder( const IndirectVectorHolder & other); 00022 IndirectVectorHolder(boost::shared_ptr<RefVectorHolderBase> p); 00023 IndirectVectorHolder(RefVectorHolderBase * p); 00024 virtual ~IndirectVectorHolder(); 00025 IndirectVectorHolder& operator= (IndirectVectorHolder const& rhs); 00026 void swap(IndirectVectorHolder& other); 00027 virtual BaseVectorHolder<T>* clone() const; 00028 virtual BaseVectorHolder<T>* cloneEmpty() const; 00029 virtual ProductID id() const; 00030 virtual EDProductGetter const* productGetter() const; 00031 virtual bool empty() const; 00032 virtual size_type size() const; 00033 virtual void clear(); 00034 virtual base_ref_type const at(size_type idx) const; 00035 virtual std::auto_ptr<reftobase::RefVectorHolderBase> vectorHolder() const { 00036 return std::auto_ptr<reftobase::RefVectorHolderBase>( helper_->clone() ); 00037 } 00038 virtual void push_back( const BaseHolder<T> * r ) { 00039 typedef IndirectHolder<T> holder_type; 00040 const holder_type * h = dynamic_cast<const holder_type *>( r ); 00041 if( h == 0 ) 00042 Exception::throwThis( errors::InvalidReference, 00043 "In IndirectHolder<T> trying to push_back wrong reference type"); 00044 helper_->push_back( h->helper_ ); 00045 } 00046 virtual const void * product() const { 00047 return helper_->product(); 00048 } 00049 00052 virtual bool isAvailable() const { return helper_->isAvailable(); } 00053 00054 private: 00055 typedef typename base_type::const_iterator_imp const_iterator_imp; 00056 RefVectorHolderBase * helper_; 00057 00058 public: 00059 struct const_iterator_imp_specific : public const_iterator_imp { 00060 typedef ptrdiff_t difference_type; 00061 const_iterator_imp_specific() { } 00062 explicit const_iterator_imp_specific( const typename RefVectorHolderBase::const_iterator & it ) : i ( it ) { } 00063 ~const_iterator_imp_specific() { } 00064 const_iterator_imp_specific * clone() const { return new const_iterator_imp_specific( i ); } 00065 void increase() { ++i; } 00066 void decrease() { --i; } 00067 void increase( difference_type d ) { i += d; } 00068 void decrease( difference_type d ) { i -= d; } 00069 bool equal_to( const const_iterator_imp * o ) const { return i == dc( o ); } 00070 bool less_than( const const_iterator_imp * o ) const { return i < dc( o ); } 00071 void assign( const const_iterator_imp * o ) { i = dc( o ); } 00072 base_ref_type deref() const { 00073 return base_ref_type( * i ); 00074 } 00075 difference_type difference( const const_iterator_imp * o ) const { return i - dc( o ); } 00076 private: 00077 const typename RefVectorHolderBase::const_iterator & dc( const const_iterator_imp * o ) const { 00078 if ( o == 0 ) { 00079 Exception::throwThis( edm::errors::InvalidReference, 00080 "In IndirectVectorHolder trying to dereference a null pointer"); 00081 } 00082 const const_iterator_imp_specific * oo = dynamic_cast<const const_iterator_imp_specific *>( o ); 00083 if ( oo == 0 ) { 00084 Exception::throwThis( errors::InvalidReference, 00085 "In IndirectVectorHolder trying to cast iterator to wrong type "); 00086 } 00087 return oo->i; 00088 } 00089 typename RefVectorHolderBase::const_iterator i; 00090 }; 00091 00092 const_iterator begin() const { 00093 return const_iterator( new const_iterator_imp_specific( helper_->begin() ) ); 00094 } 00095 const_iterator end() const { 00096 return const_iterator( new const_iterator_imp_specific( helper_->end() ) ); 00097 } 00098 }; 00099 00100 template <typename T> 00101 IndirectVectorHolder<T>::IndirectVectorHolder() : BaseVectorHolder<T>(), helper_( 0 ) { } 00102 00103 template <typename T> 00104 IndirectVectorHolder<T>::IndirectVectorHolder(boost::shared_ptr<RefVectorHolderBase> p) : 00105 BaseVectorHolder<T>(), helper_(p->clone()) { } 00106 00107 template <typename T> 00108 IndirectVectorHolder<T>::IndirectVectorHolder(RefVectorHolderBase * p) : 00109 BaseVectorHolder<T>(), helper_(p) { } 00110 00111 template <typename T> 00112 IndirectVectorHolder<T>::IndirectVectorHolder( const IndirectVectorHolder & other ) : 00113 BaseVectorHolder<T>(), helper_( other.helper_->clone() ) { } 00114 00115 template <typename T> 00116 IndirectVectorHolder<T>::~IndirectVectorHolder() { 00117 delete helper_; 00118 } 00119 00120 template <typename T> 00121 inline void IndirectVectorHolder<T>::swap(IndirectVectorHolder& other) { 00122 this->BaseVectorHolder<T>::swap(other); 00123 std::swap(helper_, other.helper_); 00124 } 00125 00126 template <typename T> 00127 inline IndirectVectorHolder<T>& 00128 IndirectVectorHolder<T>::operator=(IndirectVectorHolder const& rhs) { 00129 IndirectVectorHolder temp(rhs); 00130 swap(temp); 00131 return *this; 00132 } 00133 00134 template <typename T> 00135 BaseVectorHolder<T>* 00136 IndirectVectorHolder<T>::clone() const { 00137 return new IndirectVectorHolder<T>(*this); 00138 } 00139 00140 template <typename T> 00141 BaseVectorHolder<T>* 00142 IndirectVectorHolder<T>::cloneEmpty() const { 00143 return new IndirectVectorHolder<T>( helper_->cloneEmpty() ); 00144 } 00145 00146 template <typename T> 00147 ProductID 00148 IndirectVectorHolder<T>::id() const { 00149 return helper_->id(); 00150 } 00151 00152 template <typename T> 00153 EDProductGetter const* IndirectVectorHolder<T>::productGetter() const { 00154 return helper_->productGetter(); 00155 } 00156 00157 template <typename T> 00158 bool IndirectVectorHolder<T>::empty() const { 00159 return helper_->empty(); 00160 } 00161 00162 template <typename T> 00163 typename IndirectVectorHolder<T>::size_type IndirectVectorHolder<T>::size() const { 00164 return helper_->size(); 00165 } 00166 00167 template <typename T> 00168 void IndirectVectorHolder<T>::clear() { 00169 return helper_->clear(); 00170 } 00171 00172 template <typename T> 00173 typename IndirectVectorHolder<T>::base_ref_type const IndirectVectorHolder<T>::at(size_type idx) const { 00174 return helper_ ? helper_->template getRef<T>( idx ) : typename IndirectVectorHolder<T>::base_ref_type(); 00175 } 00176 00177 // Free swap function 00178 template <typename T> 00179 inline 00180 void swap(IndirectVectorHolder<T>& lhs, IndirectVectorHolder<T>& rhs) { 00181 lhs.swap(rhs); 00182 } 00183 } 00184 } 00185 00186 #endif 00187 00188