CMS 3D CMS Logo

DetSetRefVector.h

Go to the documentation of this file.
00001 #ifndef DataFormats_Common_DetSetRefVector_h
00002 #define DataFormats_Common_DetSetRefVector_h
00003 
00004 /*----------------------------------------------------------------------
00005   
00006 DetSeReftVector: A collection of homogeneous objects that can be used for
00007 an EDProduct. DetSetVector is *not* designed for use as a base class
00008 (it has no virtual functions).
00009 
00010 DetSetVector<T> contains a vector<DetSet<T> >, sorted on DetId, and
00011 provides fast (O(log n)) lookups, but only O(n) insertion.
00012 
00013 It provides an interface such that EdmRef2 can directly reference, and
00014 provide access to, individual T objects.
00015 
00016 The collection appears to the user as if it were a sequence of
00017 DetSet<T>; e.g., operator[] returns a DetSet<T>&. However, the
00018 argument to operator[] specifies the (DetId) identifier of the vector
00019 to be returned, *not* the ordinal number of the T to be returned.
00020 
00021                           ------------------
00022    It is critical that users DO NOT MODIFY the id data member of a
00023    DetSet object in a DetSetVector.
00024                           ------------------
00025 
00026 $Id: DetSetRefVector.h,v 1.11 2008/03/31 21:12:11 wmtan Exp $
00027 
00028 ----------------------------------------------------------------------*/
00029 
00030 #include <algorithm>
00031 #include <vector>
00032 
00033 #include "boost/concept_check.hpp"
00034 #include "boost/iterator/indirect_iterator.hpp"
00035 
00036 #include "DataFormats/Common/interface/traits.h"
00037 #include "DataFormats/Common/interface/DetSet.h"
00038 #include "FWCore/Utilities/interface/EDMException.h"
00039 
00040 #include "DataFormats/Common/interface/Ref.h"
00041 #include "DataFormats/Common/interface/DetSetVector.h"
00042 #include "DataFormats/Common/interface/Handle.h"
00043 #include "DataFormats/Common/interface/OrphanHandle.h"
00044 #include "DataFormats/Common/interface/TestHandle.h"
00045 
00046 namespace edm {
00047 
00048   //------------------------------------------------------------
00049   // Forward declarations
00050   template <typename T, typename C> class DetSetRefVector;
00051 
00052   //------------------------------------------------------------
00053   // Helper function, to regularize throwing of exceptions.
00054   //------------------------------------------------------------
00055 
00056   namespace dsrvdetail
00057   {
00058     // Throw an edm::Exception with an appropriate message
00059     inline
00060     void _throw_range(det_id_type i)
00061     {
00062       throw edm::Exception(errors::InvalidReference)
00063         << "DetSetRefVector::operator[] called with index not in collection;\n"
00064         << "index value: " << i;
00065     }
00066   }
00067 
00068   //------------------------------------------------------------
00069   //
00070   namespace refhelper {
00071     template<typename T, typename C >
00072     struct FindDetSetForDetSetVector : public std::binary_function<const C &, edm::det_id_type, const DetSet<T>*> {
00073       typedef FindDetSetForDetSetVector<T,C> self;
00074       typename self::result_type operator()(typename self::first_argument_type iContainer,  typename self::second_argument_type iIndex) const {
00075         return &(*(iContainer.find(iIndex)));
00076       }
00077     };
00078   }
00079   
00080   //allow comparison of edm::Ref<...> to the det_it_type.  This allows searching without dereferencing the edm::Ref
00081   template <typename T, typename C=DetSetVector<T> >
00082     struct CompareRefDetSet {
00083     typedef Ref<C, DetSet<T>, refhelper::FindDetSetForDetSetVector<T,C> > ref_type; 
00084       bool operator()(const ref_type& iRef, det_id_type iId) {
00085         return iRef.key() < iId;
00086       }
00087       bool operator()(det_id_type iId, const ref_type& iRef) {
00088         return iId < iRef.key();
00089       }
00090     };
00091 
00092   template <typename T, typename C=DetSetVector<T> >
00093   class DetSetRefVector 
00094   {
00097     BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept);
00098   public:
00099 
00100     typedef DetSet<T>           detset;
00101     typedef detset              value_type;
00102     typedef Ref<C, DetSet<T>, refhelper::FindDetSetForDetSetVector<T,C> > ref_type;
00103     typedef std::vector<ref_type> collection_type;
00104 
00105     typedef detset const&  const_reference;
00106 
00107     //iterator returns a DetSet<T> instead of a Ref<...>
00108     typedef boost::indirect_iterator<typename collection_type::const_iterator> const_iterator;
00109     typedef typename collection_type::size_type      size_type;
00110 
00113 
00114     // Add the following only if needed.
00115     //template <class InputIterator>
00116     //DetSetRefVector(InputIterator b, InputIterator e);
00117 
00118     DetSetRefVector() {}
00119     
00120       DetSetRefVector(const Handle<C>& iHandle, const std::vector<det_id_type>& iDets) : sets_() {
00121         sets_.reserve(iDets.size());
00122         det_id_type sanityCheck = 0;
00123         for(std::vector<det_id_type>::const_iterator itDetId = iDets.begin(),
00124             itDetIdEnd = iDets.end();
00125             itDetId != itDetIdEnd;
00126             ++itDetId) {
00127           assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
00128           sanityCheck = *itDetId;
00129           //the last 'false' says to not get the data right now
00130           sets_.push_back(ref_type(iHandle, *itDetId, false));
00131         }
00132       }
00133 
00134       DetSetRefVector(const OrphanHandle<C>& iHandle, const std::vector<det_id_type>& iDets) : sets_() {
00135         sets_.reserve(iDets.size());
00136         det_id_type sanityCheck = 0;
00137         for(std::vector<det_id_type>::const_iterator itDetId = iDets.begin(),
00138             itDetIdEnd = iDets.end();
00139             itDetId != itDetIdEnd;
00140             ++itDetId) {
00141           assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
00142           sanityCheck = *itDetId;
00143           //the last 'false' says to not get the data right now
00144           sets_.push_back(ref_type(iHandle, *itDetId, false));
00145         }
00146       }
00147 
00148       DetSetRefVector(const TestHandle<C>& iHandle, const std::vector<det_id_type>& iDets) : sets_() {
00149         sets_.reserve(iDets.size());
00150         det_id_type sanityCheck = 0;
00151         for(std::vector<det_id_type>::const_iterator itDetId = iDets.begin(),
00152             itDetIdEnd = iDets.end();
00153             itDetId != itDetIdEnd;
00154             ++itDetId) {
00155           assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
00156           sanityCheck = *itDetId;
00157           //the last 'false' says to not get the data right now
00158           sets_.push_back(ref_type(iHandle, *itDetId, false));
00159         }
00160       }
00161 
00162     void swap(DetSetRefVector& other);
00163 
00164     DetSetRefVector& operator=(DetSetRefVector const& rhs);
00165 
00167     bool empty() const;
00168 
00170     size_type size() const;
00171 
00172     // Do we need a short-hand method to return the number of T
00173     // instances? If so, do we optimize for size (calculate on the
00174     // fly) or speed (keep a current cache)?
00175 
00178     const_iterator find(det_id_type id) const;
00179 
00183     const_reference operator[](det_id_type i) const;
00184 
00186     const_iterator begin() const;
00187 
00189     const_iterator end() const;
00190 
00193     //void post_insert();
00194 
00195   private:
00196     collection_type   sets_;
00197 
00198   };
00199 
00200   template <typename T, typename C>
00201   inline
00202   void
00203   DetSetRefVector<T,C>::swap(DetSetRefVector<T,C>& other) {
00204     sets_.swap(other.sets_);
00205   }
00206 
00207   template <typename T, typename C>
00208   inline
00209   DetSetRefVector<T ,C>&
00210   DetSetRefVector<T, C>::operator=(DetSetRefVector<T,C> const& rhs) {
00211     DetSetRefVector<T, C> temp(rhs);
00212     this->swap(temp);
00213     return *this;
00214   }
00215 
00216   template <typename T, typename C>
00217   inline
00218   bool
00219   DetSetRefVector<T,C>::empty() const 
00220   {
00221     return sets_.empty();
00222   }
00223 
00224   template <typename T, typename C>
00225   inline
00226   typename DetSetRefVector<T,C>::size_type
00227   DetSetRefVector<T,C>::size() const
00228   {
00229     return sets_.size();
00230   }
00231 
00232   template <typename T, typename C>
00233   inline
00234   typename DetSetRefVector<T,C>::const_iterator
00235   DetSetRefVector<T,C>::find(det_id_type id) const
00236   {
00237     if(empty()) {
00238       return sets_.end();
00239     }
00240     std::pair<typename collection_type::const_iterator,typename collection_type::const_iterator> p = 
00241     std::equal_range(sets_.begin(), sets_.end(), id, CompareRefDetSet<T,C>());
00242     if (p.first == p.second) return sets_.end();
00243     // The range indicated by [p.first, p.second) should be exactly of
00244     // length 1.
00245     assert(std::distance(p.first, p.second) == 1);
00246     return p.first;
00247   }
00248 
00249   template <typename T, typename C>
00250   inline
00251   typename DetSetRefVector<T,C>::const_reference
00252   DetSetRefVector<T,C>::operator[](det_id_type i) const 
00253   {
00254     // Find the right DetSet, and return a reference to it.  Throw if
00255     // there is none.
00256     const_iterator it = this->find(i);
00257     if (it == this->end()) dsrvdetail::_throw_range(i);
00258     return *it;
00259   }
00260 
00261   template <typename T, typename C>
00262   inline
00263   typename DetSetRefVector<T,C>::const_iterator
00264   DetSetRefVector<T,C>::begin() const
00265   {
00266     return sets_.begin();
00267   }
00268 
00269   template <typename T, typename C>
00270   inline
00271   typename DetSetRefVector<T,C>::const_iterator
00272   DetSetRefVector<T,C>::end() const
00273   {
00274     return sets_.end();
00275   }
00276 
00277   // Free swap function
00278   template <typename T, typename C>
00279   inline
00280   void
00281   swap(DetSetRefVector<T, C>& a, DetSetRefVector<T, C>& b) {
00282     a.swap(b);
00283   }
00284 
00285 //specialize behavior of edm::Ref to get access to the 'Det'
00286 
00287   namespace refhelper {
00288     template<typename T, typename C>
00289     struct FindForDetSetRefVector : public std::binary_function<const DetSetRefVector<T,C>&, std::pair<det_id_type, typename DetSet<T>::collection_type::size_type>, const T*> {
00290       typedef FindForDetSetRefVector<T,C> self;
00291       typename self::result_type operator()(typename self::first_argument_type iContainer,  typename self::second_argument_type iIndex) {
00292         return &(*(iContainer.find(iIndex.first)->data.begin()+iIndex.second));
00293       }
00294     };
00295     
00296     template<typename T, typename C> 
00297       struct FindTrait<DetSetRefVector<T,C>,T> {
00298         typedef FindForDetSetRefVector<T,C> value;
00299       };
00300   }
00301   
00302    //helper function to make it easier to create a edm::Ref
00303    
00304    template<class HandleT>
00305    Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type> 
00306    makeRefToDetSetRefVector(const HandleT& iHandle, 
00307              det_id_type iDetID,
00308              typename HandleT::element_type::value_type::const_iterator itIter) {
00309       typedef typename HandleT::element_type Vec;
00310       typename Vec::value_type::collection_type::size_type index=0;
00311       typename Vec::const_iterator itFound = iHandle->find(iDetID);
00312       index += (itIter- itFound->data.begin());
00313       return    Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type> (iHandle,std::make_pair(iDetID,index));
00314    }
00315    
00316    template<class HandleT>
00317    Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type> 
00318    makeRefToDetSetRefVector(const HandleT& iHandle, 
00319              det_id_type iDetID,
00320              typename HandleT::element_type::value_type::iterator itIter) {
00321       typedef typename HandleT::element_type Vec;
00322       typename Vec::detset::const_iterator itIter2 = itIter;
00323       return makeRefToDetSetRefVector(iHandle,iDetID,itIter2);
00324    }
00325 }  
00326 #endif

Generated on Tue Jun 9 17:28:45 2009 for CMSSW by  doxygen 1.5.4