Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:52:57

0001 #ifndef DataFormats_Common_DetSetRefVector_h
0002 #define DataFormats_Common_DetSetRefVector_h
0003 
0004 /*----------------------------------------------------------------------
0005   
0006 DetSeReftVector: A collection of homogeneous objects that can be used for
0007 an EDProduct. DetSetVector is *not* designed for use as a base class
0008 (it has no virtual functions).
0009 
0010 DetSetVector<T> contains a vector<DetSet<T> >, sorted on DetId, and
0011 provides fast (O(log n)) lookups, but only O(n) insertion.
0012 
0013 It provides an interface such that EdmRef2 can directly reference, and
0014 provide access to, individual T objects.
0015 
0016 The collection appears to the user as if it were a sequence of
0017 DetSet<T>; e.g., operator[] returns a DetSet<T>&. However, the
0018 argument to operator[] specifies the (DetId) identifier of the vector
0019 to be returned, *not* the ordinal number of the T to be returned.
0020 
0021               ------------------
0022    It is critical that users DO NOT MODIFY the id data member of a
0023    DetSet object in a DetSetVector.
0024               ------------------
0025 
0026 ----------------------------------------------------------------------*/
0027 
0028 #include <algorithm>
0029 #include <vector>
0030 
0031 #include "boost/concept_check.hpp"
0032 #include "boost/iterator/indirect_iterator.hpp"
0033 
0034 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
0035 #include "DataFormats/Common/interface/traits.h"
0036 #include "DataFormats/Common/interface/DetSet.h"
0037 #include "FWCore/Utilities/interface/EDMException.h"
0038 
0039 #include "DataFormats/Common/interface/Ref.h"
0040 #include "DataFormats/Common/interface/DetSetVector.h"
0041 #include "DataFormats/Common/interface/Handle.h"
0042 #include "DataFormats/Common/interface/OrphanHandle.h"
0043 #include "DataFormats/Common/interface/TestHandle.h"
0044 
0045 namespace edm {
0046 
0047   //------------------------------------------------------------
0048   // Forward declarations
0049   template <typename T, typename C>
0050   class DetSetRefVector;
0051 
0052   //------------------------------------------------------------
0053   // Helper function, to regularize throwing of exceptions.
0054   //------------------------------------------------------------
0055 
0056   namespace dsrvdetail {
0057     // Throw an edm::Exception with an appropriate message
0058     inline void _throw_range(det_id_type i) {
0059       Exception::throwThis(errors::InvalidReference,
0060                            "DetSetRefVector::operator[] called with index not in collection;\nindex value: ",
0061                            i);
0062     }
0063   }  // namespace dsrvdetail
0064 
0065   //------------------------------------------------------------
0066   //
0067   namespace refhelper {
0068     template <typename T, typename C>
0069     struct FindDetSetForDetSetVector {
0070       using result_type = DetSet<T> const*;
0071       using first_argument_type = C const&;
0072       using second_argument_type = edm::det_id_type const;
0073 
0074       result_type operator()(first_argument_type iContainer, second_argument_type iIndex) const {
0075         return &(*(iContainer.find(iIndex)));
0076       }
0077     };
0078   }  // namespace refhelper
0079 
0080   //allow comparison of edm::Ref<...> to the det_it_type.  This allows searching without dereferencing the edm::Ref
0081   template <typename T, typename C = DetSetVector<T> >
0082   struct CompareRefDetSet {
0083     typedef Ref<C, DetSet<T>, refhelper::FindDetSetForDetSetVector<T, C> > ref_type;
0084     bool operator()(const ref_type& iRef, det_id_type iId) { return iRef.key() < iId; }
0085     bool operator()(det_id_type iId, const ref_type& iRef) { return iId < iRef.key(); }
0086   };
0087 
0088   template <typename T, typename C = DetSetVector<T> >
0089   class DetSetRefVector {
0090     /// DetSetVector requires that T objects can be compared with
0091     /// operator<.
0092     BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept);
0093 
0094   public:
0095     typedef DetSet<T> detset;
0096     typedef detset value_type;
0097     typedef Ref<C, DetSet<T>, refhelper::FindDetSetForDetSetVector<T, C> > ref_type;
0098     typedef std::vector<ref_type> collection_type;
0099 
0100     typedef detset const& const_reference;
0101 
0102     //iterator returns a DetSet<T> instead of a Ref<...>
0103     typedef boost::indirect_iterator<typename collection_type::const_iterator> const_iterator;
0104     typedef typename collection_type::size_type size_type;
0105 
0106     /// Compiler-generated default c'tor, copy c'tor, d'tor and
0107     /// assignment are correct.
0108 
0109     // Add the following only if needed.
0110     //template <class InputIterator>
0111     //DetSetRefVector(InputIterator b, InputIterator e);
0112 
0113     DetSetRefVector() {}
0114 
0115     DetSetRefVector(const Handle<C>& iHandle, const std::vector<det_id_type>& iDets) : sets_() {
0116       sets_.reserve(iDets.size());
0117       det_id_type sanityCheck = 0;
0118       for (std::vector<det_id_type>::const_iterator itDetId = iDets.begin(), itDetIdEnd = iDets.end();
0119            itDetId != itDetIdEnd;
0120            ++itDetId) {
0121         assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
0122         sanityCheck = *itDetId;
0123         //the last 'false' says to not get the data right now
0124         sets_.push_back(ref_type(iHandle, *itDetId, false));
0125       }
0126     }
0127 
0128     DetSetRefVector(const OrphanHandle<C>& iHandle, const std::vector<det_id_type>& iDets) : sets_() {
0129       sets_.reserve(iDets.size());
0130       det_id_type sanityCheck = 0;
0131       for (std::vector<det_id_type>::const_iterator itDetId = iDets.begin(), itDetIdEnd = iDets.end();
0132            itDetId != itDetIdEnd;
0133            ++itDetId) {
0134         assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
0135         sanityCheck = *itDetId;
0136         //the last 'false' says to not get the data right now
0137         sets_.push_back(ref_type(iHandle, *itDetId, false));
0138       }
0139     }
0140 
0141     DetSetRefVector(const TestHandle<C>& iHandle, const std::vector<det_id_type>& iDets) : sets_() {
0142       sets_.reserve(iDets.size());
0143       det_id_type sanityCheck = 0;
0144       for (std::vector<det_id_type>::const_iterator itDetId = iDets.begin(), itDetIdEnd = iDets.end();
0145            itDetId != itDetIdEnd;
0146            ++itDetId) {
0147         assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
0148         sanityCheck = *itDetId;
0149         //the last 'false' says to not get the data right now
0150         sets_.push_back(ref_type(iHandle, *itDetId, false));
0151       }
0152     }
0153 
0154     void swap(DetSetRefVector& other);
0155 
0156     DetSetRefVector& operator=(DetSetRefVector const& rhs);
0157 
0158     /// Return true if we contain no DetSets.
0159     bool empty() const;
0160 
0161     /// Return the number of contained DetSets
0162     size_type size() const;
0163 
0164     // Do we need a short-hand method to return the number of T
0165     // instances? If so, do we optimize for size (calculate on the
0166     // fly) or speed (keep a current cache)?
0167 
0168     /// Return an iterator to the DetSet with the given id, or end()
0169     /// if there is no such DetSet.
0170     const_iterator find(det_id_type id) const;
0171 
0172     /// Return a reference to the DetSet with the given detector
0173     /// ID. If there is no such DetSet, we throw an edm::Exception.
0174     /// **DO NOT MODIFY THE id DATA MEMBER OF THE REFERENCED DetSet!**
0175     const_reference operator[](det_id_type i) const;
0176 
0177     /// Return an iterator to the first DetSet.
0178     const_iterator begin() const;
0179 
0180     /// Return the off-the-end iterator.
0181     const_iterator end() const;
0182 
0183     /// This function will be called by the edm::Event after the
0184     /// DetSetVector has been inserted into the Event.
0185     //void post_insert();
0186 
0187     //Needed for ROOT storage
0188     CMS_CLASS_VERSION(10)
0189 
0190   private:
0191     collection_type sets_;
0192   };
0193 
0194   template <typename T, typename C>
0195   inline void DetSetRefVector<T, C>::swap(DetSetRefVector<T, C>& other) {
0196     sets_.swap(other.sets_);
0197   }
0198 
0199   template <typename T, typename C>
0200   inline DetSetRefVector<T, C>& DetSetRefVector<T, C>::operator=(DetSetRefVector<T, C> const& rhs) {
0201     DetSetRefVector<T, C> temp(rhs);
0202     this->swap(temp);
0203     return *this;
0204   }
0205 
0206   template <typename T, typename C>
0207   inline bool DetSetRefVector<T, C>::empty() const {
0208     return sets_.empty();
0209   }
0210 
0211   template <typename T, typename C>
0212   inline typename DetSetRefVector<T, C>::size_type DetSetRefVector<T, C>::size() const {
0213     return sets_.size();
0214   }
0215 
0216   template <typename T, typename C>
0217   inline typename DetSetRefVector<T, C>::const_iterator DetSetRefVector<T, C>::find(det_id_type id) const {
0218     if (empty()) {
0219       return sets_.end();
0220     }
0221     std::pair<typename collection_type::const_iterator, typename collection_type::const_iterator> p =
0222         std::equal_range(sets_.begin(), sets_.end(), id, CompareRefDetSet<T, C>());
0223     if (p.first == p.second)
0224       return sets_.end();
0225     // The range indicated by [p.first, p.second) should be exactly of
0226     // length 1.
0227     assert(std::distance(p.first, p.second) == 1);
0228     return p.first;
0229   }
0230 
0231   template <typename T, typename C>
0232   inline typename DetSetRefVector<T, C>::const_reference DetSetRefVector<T, C>::operator[](det_id_type i) const {
0233     // Find the right DetSet, and return a reference to it.  Throw if
0234     // there is none.
0235     const_iterator it = this->find(i);
0236     if (it == this->end())
0237       dsrvdetail::_throw_range(i);
0238     return *it;
0239   }
0240 
0241   template <typename T, typename C>
0242   inline typename DetSetRefVector<T, C>::const_iterator DetSetRefVector<T, C>::begin() const {
0243     return sets_.begin();
0244   }
0245 
0246   template <typename T, typename C>
0247   inline typename DetSetRefVector<T, C>::const_iterator DetSetRefVector<T, C>::end() const {
0248     return sets_.end();
0249   }
0250 
0251   // Free swap function
0252   template <typename T, typename C>
0253   inline void swap(DetSetRefVector<T, C>& a, DetSetRefVector<T, C>& b) {
0254     a.swap(b);
0255   }
0256 
0257   //specialize behavior of edm::Ref to get access to the 'Det'
0258 
0259   namespace refhelper {
0260     template <typename T, typename C>
0261     struct FindForDetSetRefVector {
0262       using result_type = T const*;
0263       using first_argument_type = DetSetRefVector<T, C> const&;
0264       using second_argument_type = std::pair<det_id_type, typename DetSet<T>::collection_type::size_type>;
0265 
0266       result_type operator()(first_argument_type iContainer, second_argument_type iIndex) {
0267         return &(*(iContainer.find(iIndex.first)->data.begin() + iIndex.second));
0268       }
0269     };
0270 
0271     template <typename T, typename C>
0272     struct FindTrait<DetSetRefVector<T, C>, T> {
0273       typedef FindForDetSetRefVector<T, C> value;
0274     };
0275   }  // namespace refhelper
0276 
0277   //helper function to make it easier to create a edm::Ref
0278 
0279   template <class HandleT>
0280   Ref<typename HandleT::element_type, typename HandleT::element_type::value_type::value_type> makeRefToDetSetRefVector(
0281       const HandleT& iHandle, det_id_type iDetID, typename HandleT::element_type::value_type::const_iterator itIter) {
0282     typedef typename HandleT::element_type Vec;
0283     typename Vec::value_type::collection_type::size_type index = 0;
0284     typename Vec::const_iterator itFound = iHandle->find(iDetID);
0285     index += (itIter - itFound->data.begin());
0286     return Ref<typename HandleT::element_type, typename HandleT::element_type::value_type::value_type>(
0287         iHandle, std::make_pair(iDetID, index));
0288   }
0289 
0290   template <class HandleT>
0291   Ref<typename HandleT::element_type, typename HandleT::element_type::value_type::value_type> makeRefToDetSetRefVector(
0292       const HandleT& iHandle, det_id_type iDetID, typename HandleT::element_type::value_type::iterator itIter) {
0293     typedef typename HandleT::element_type Vec;
0294     typename Vec::detset::const_iterator itIter2 = itIter;
0295     return makeRefToDetSetRefVector(iHandle, iDetID, itIter2);
0296   }
0297 }  // namespace edm
0298 #endif