Go to the documentation of this file.00001 #ifndef DataFormats_Common_DetSetLazyVector_h
00002 #define DataFormats_Common_DetSetLazyVector_h
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <algorithm>
00029 #include <vector>
00030
00031 #include "boost/concept_check.hpp"
00032 #include "boost/iterator/transform_iterator.hpp"
00033 #include "boost/shared_ptr.hpp"
00034
00035 #include "DataFormats/Common/interface/traits.h"
00036 #include "DataFormats/Common/interface/DetSet.h"
00037 #include "FWCore/Utilities/interface/EDMException.h"
00038 #include "DataFormats/Common/interface/Ref.h"
00039
00040 namespace edm {
00041
00042
00043
00044 template <class T> class DetSetLazyVector;
00045
00046
00047
00048
00049
00050 namespace dslvdetail
00051 {
00052
00053 inline
00054 void _throw_range(det_id_type i)
00055 {
00056 Exception::throwThis(errors::InvalidReference,
00057 "DetSetLazyVector::operator[] called with index not in collection;\nindex value: ", i);
00058 }
00059 }
00060
00061 namespace dslv {
00062 template< typename T>
00063 class LazyGetter {
00064 public:
00065 virtual ~LazyGetter() {}
00066 virtual void fill(DetSet<T>&) = 0;
00067 };
00068 template<typename T>
00069 struct LazyAdapter : public std::unary_function<const DetSet<T>&, const DetSet<T>&> {
00070 LazyAdapter(boost::shared_ptr<LazyGetter<T> > iGetter): getter_(iGetter) {}
00071 const DetSet<T>& operator()(const DetSet<T>& iUpdate) const {
00072 if(iUpdate.data.empty() && getter_) {
00073
00074 DetSet<T>& temp = const_cast< DetSet<T>& >(iUpdate);
00075 getter_->fill(temp);
00076 std::sort(temp.begin(),temp.end());
00077 }
00078 return iUpdate;
00079 }
00080 private:
00081 boost::shared_ptr<LazyGetter<T> > getter_;
00082 };
00083 }
00084
00085
00086 namespace refhelper {
00087 template<typename T>
00088 struct FindDetSetForDetSetLazyVector : public std::binary_function<const DetSetLazyVector<T>&, edm::det_id_type, const DetSet<T>*> {
00089 typedef FindDetSetForDetSetLazyVector<T> self;
00090 typename self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex) const {
00091 return &(*(iContainer.find(iIndex)));
00092 }
00093 };
00094 }
00095
00096 template <class T>
00097 class DetSetLazyVector
00098 {
00101 BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept);
00102 public:
00103
00104 typedef DetSet<T> detset;
00105 typedef detset value_type;
00106 typedef std::vector<value_type> collection_type;
00107
00108 typedef detset const& const_reference;
00109
00110
00111 typedef boost::transform_iterator< dslv::LazyAdapter<T>, typename collection_type::const_iterator > const_iterator;
00112 typedef typename collection_type::size_type size_type;
00113
00116
00117
00118
00119
00120
00121 DetSetLazyVector() {}
00122
00123 DetSetLazyVector(boost::shared_ptr<dslv::LazyGetter<T> > iGetter, const std::vector<det_id_type>& iDets) :
00124 sets_(),
00125 getter_(iGetter) {
00126 sets_.reserve(iDets.size());
00127 det_id_type sanityCheck = 0;
00128 for(std::vector<det_id_type>::const_iterator itDetId = iDets.begin(), itDetIdEnd = iDets.end();
00129 itDetId != itDetIdEnd;
00130 ++itDetId) {
00131 assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
00132 sanityCheck = *itDetId;
00133 sets_.push_back(DetSet<T>(*itDetId));
00134 }
00135 }
00136
00137 void swap(DetSetLazyVector& other);
00138
00139
00140
00142 bool empty() const;
00143
00145 size_type size() const;
00146
00147
00148
00149
00150
00153 const_iterator find(det_id_type id) const;
00154
00158 const_reference operator[](det_id_type i) const;
00159
00161 const_iterator begin() const;
00162
00164 const_iterator end() const;
00165
00168
00169
00170 private:
00171 collection_type sets_;
00172 boost::shared_ptr<dslv::LazyGetter<T> > getter_;
00173 };
00174
00175 template <class T>
00176 inline
00177 void
00178 DetSetLazyVector<T>::swap(DetSetLazyVector<T>& other)
00179 {
00180 sets_.swap(other.sets_);
00181 std::swap(getter_,other.getter_);
00182 }
00183
00184 template <class T>
00185 inline
00186 bool
00187 DetSetLazyVector<T>::empty() const
00188 {
00189 return sets_.empty();
00190 }
00191
00192 template <class T>
00193 inline
00194 typename DetSetLazyVector<T>::size_type
00195 DetSetLazyVector<T>::size() const
00196 {
00197 return sets_.size();
00198 }
00199
00200 template <class T>
00201 inline
00202 typename DetSetLazyVector<T>::const_iterator
00203 DetSetLazyVector<T>::find(det_id_type id) const
00204 {
00205 if(empty()) {
00206 dslv::LazyAdapter<T> adapter(getter_);
00207 return boost::make_transform_iterator(sets_.end(),adapter);
00208 }
00209
00210
00211 std::pair<typename collection_type::const_iterator,typename collection_type::const_iterator> p =
00212 std::equal_range(sets_.begin(), sets_.end(), id);
00213 if (p.first == p.second) {
00214 dslv::LazyAdapter<T> adapter(getter_);
00215 return boost::make_transform_iterator(sets_.end(),adapter);
00216 }
00217
00218
00219 assert(std::distance(p.first, p.second) == 1);
00220 dslv::LazyAdapter<T> adapter(getter_);
00221 return boost::make_transform_iterator(p.first,adapter);
00222 }
00223
00224 template <class T>
00225 inline
00226 typename DetSetLazyVector<T>::const_reference
00227 DetSetLazyVector<T>::operator[](det_id_type i) const
00228 {
00229
00230
00231 const_iterator it = this->find(i);
00232 if (it == this->end()) dslvdetail::_throw_range(i);
00233 return *it;
00234 }
00235
00236 template <class T>
00237 inline
00238 typename DetSetLazyVector<T>::const_iterator
00239 DetSetLazyVector<T>::begin() const
00240 {
00241 dslv::LazyAdapter<T> adapter(getter_);
00242 return boost::make_transform_iterator(sets_.begin(),adapter);
00243 }
00244
00245 template <class T>
00246 inline
00247 typename DetSetLazyVector<T>::const_iterator
00248 DetSetLazyVector<T>::end() const
00249 {
00250 dslv::LazyAdapter<T> adapter(getter_);
00251 return boost::make_transform_iterator(sets_.end(),adapter);
00252 }
00253
00254
00255 template <class T>
00256 inline
00257 void
00258 swap(DetSetLazyVector<T>& a, DetSetLazyVector<T>& b)
00259 {
00260 a.swap(b);
00261 }
00262
00263
00264
00265 namespace refhelper {
00266 template<typename T>
00267 struct FindForDetSetLazyVector : public std::binary_function<const DetSetLazyVector<T>&, std::pair<det_id_type, typename DetSet<T>::collection_type::size_type>, const T*> {
00268 typedef FindForDetSetLazyVector<T> self;
00269 typename self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex) {
00270 return &(*(iContainer.find(iIndex.first)->data.begin()+iIndex.second));
00271 }
00272 };
00273
00274 template<typename T>
00275 struct FindTrait<DetSetLazyVector<T>,T> {
00276 typedef FindForDetSetLazyVector<T> value;
00277 };
00278 }
00279
00280
00281
00282 template<class HandleT>
00283 Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type>
00284 makeRefToDetSetLazyVector(const HandleT& iHandle,
00285 det_id_type iDetID,
00286 typename HandleT::element_type::value_type::const_iterator itIter) {
00287 typedef typename HandleT::element_type Vec;
00288 typename Vec::value_type::collection_type::size_type index=0;
00289 typename Vec::const_iterator itFound = iHandle->find(iDetID);
00290 index += (itIter- itFound->data.begin());
00291 return Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type> (iHandle,std::make_pair(iDetID,index));
00292 }
00293
00294 template<class HandleT>
00295 Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type>
00296 makeRefToDetSetLazyVector(const HandleT& iHandle,
00297 det_id_type iDetID,
00298 typename HandleT::element_type::value_type::iterator itIter) {
00299 typedef typename HandleT::element_type Vec;
00300 typename Vec::detset::const_iterator itIter2 = itIter;
00301 return makeRefToDetSetLazyVector(iHandle,iDetID,itIter2);
00302 }
00303 }
00304 #endif