Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:03:55

0001 #ifndef DataFormats_Common_View_h
0002 #define DataFormats_Common_View_h
0003 // -*- C++ -*-
0004 //
0005 // Package:     Framework
0006 // Class  :     View
0007 //
0008 /**\class edm::View<T>
0009 
0010 Description: Provide access to the collected elements contained by any WrapperBase that is a sequence.
0011 
0012 */
0013 //
0014 // Original Author:
0015 //         Created:  Mon Dec 18 09:48:30 CST 2006
0016 //
0017 
0018 #include "DataFormats/Common/interface/Ptr.h"
0019 #include "DataFormats/Common/interface/RefToBase.h"
0020 #include "DataFormats/Common/interface/IndirectHolder.h"
0021 #include "DataFormats/Common/interface/RefHolder_.h"
0022 #include "boost/iterator/indirect_iterator.hpp"
0023 
0024 #include <vector>
0025 #include <memory>
0026 #include <algorithm>
0027 #include <iterator>
0028 #include <utility>
0029 #include <cassert>
0030 
0031 namespace edm {
0032   class EDProductGetter;
0033 
0034   //------------------------------------------------------------------
0035   // Class ViewBase
0036   //
0037   // ViewBase is an abstract base class. It exists only so that we
0038   // make invoke View<T> destructors polymorphically, and copy them
0039   // using clone().
0040   //
0041   //------------------------------------------------------------------
0042 
0043   class ViewBase {
0044   public:
0045     virtual ~ViewBase();
0046     std::unique_ptr<ViewBase> clone() const;
0047 
0048   protected:
0049     ViewBase() = default;
0050     ViewBase(ViewBase const&) = default;
0051     ViewBase(ViewBase&&) = default;
0052     ViewBase& operator=(ViewBase const&) = default;
0053     ViewBase& operator=(ViewBase&&) = default;
0054     virtual std::unique_ptr<ViewBase> doClone() const = 0;
0055     void swap(ViewBase&) {}  // Nothing to swap
0056   };
0057 
0058   //------------------------------------------------------------------
0059   /// Class template View<T>
0060   ///
0061   /// View<T> provides a way to allow reference to the elements (of
0062   /// type T) of some collection in an Event, without knowing about the
0063   /// type of the collection itself. For example, View<int> can refer
0064   /// to the ints in either a vector<int> or a list<int>, without the
0065   /// client code knowing about which type of container manages the
0066   /// ints.
0067   ///
0068   /// View<T> is not persistable.
0069   ///
0070   /// View<T> can be used to reference objects of any type that has T
0071   /// as a public base.
0072   ///
0073   //------------------------------------------------------------------
0074 
0075   template <typename T>
0076   class View : public ViewBase {
0077     typedef std::vector<T const*> seq_t;
0078 
0079   public:
0080     typedef T const* pointer;
0081     typedef T const* const_pointer;
0082 
0083     typedef T const& reference;
0084     typedef T const& const_reference;
0085 
0086     typedef T value_type;
0087 
0088     typedef boost::indirect_iterator<typename seq_t::const_iterator> const_iterator;
0089 
0090     // This should be a typedef to seq_t::size_type but because this type is used as a template
0091     // argument in a persistened class it must be stable for different architectures
0092     typedef unsigned int size_type;
0093     typedef typename seq_t::difference_type difference_type;
0094 
0095     typedef boost::indirect_iterator<typename seq_t::const_reverse_iterator> const_reverse_iterator;
0096 
0097     // Compiler-generated copy, and assignment each does the right
0098     // thing.
0099 
0100     View();
0101 
0102     // This function is dangerous, and should only be called from the
0103     // infrastructure code.
0104     View(std::vector<void const*> const& pointers, FillViewHelperVector const& helpers, EDProductGetter const* getter);
0105 
0106     void swap(View& other);
0107 
0108     size_type capacity() const;
0109 
0110     // Most non-const member functions not present.
0111     // No access to non-const contents provided.
0112 
0113     const_iterator begin() const;
0114     const_iterator end() const;
0115 
0116     const_reverse_iterator rbegin() const;
0117     const_reverse_iterator rend() const;
0118 
0119     size_type size() const;
0120     size_type max_size() const;
0121     bool empty() const;
0122     const_reference at(size_type pos) const;
0123     const_reference operator[](size_type pos) const;
0124     RefToBase<value_type> refAt(size_type i) const;
0125     Ptr<value_type> ptrAt(size_type i) const;
0126     std::vector<Ptr<value_type>> const& ptrs() const;
0127 
0128     const_reference front() const;
0129     const_reference back() const;
0130 
0131     // No erase, because erase is required to return an *iterator*,
0132     // not a *const_iterator*.
0133 
0134     // The following is for testing only.
0135     static void fill_from_range(T* first, T* last, View& output);
0136 
0137   private:
0138     seq_t items_;
0139     std::vector<Ptr<value_type>> vPtrs_;
0140     std::unique_ptr<ViewBase> doClone() const override;
0141   };
0142 
0143   // Associated free functions (same as for std::vector)
0144   template <typename T>
0145   bool operator==(View<T> const&, View<T> const&);
0146   template <typename T>
0147   bool operator!=(View<T> const&, View<T> const&);
0148   template <typename T>
0149   bool operator<(View<T> const&, View<T> const&);
0150   template <typename T>
0151   bool operator<=(View<T> const&, View<T> const&);
0152   template <typename T>
0153   bool operator>(View<T> const&, View<T> const&);
0154   template <typename T>
0155   bool operator>=(View<T> const&, View<T> const&);
0156 
0157   //------------------------------------------------------------------
0158   // Implementation of View<T>
0159   //------------------------------------------------------------------
0160 
0161   template <typename T>
0162   inline View<T>::View() : items_(), vPtrs_() {}
0163 
0164   template <typename T>
0165   View<T>::View(std::vector<void const*> const& pointers,
0166                 FillViewHelperVector const& helpers,
0167                 EDProductGetter const* getter)
0168       : items_(), vPtrs_() {
0169     size_type numElements = pointers.size();
0170 
0171     // If the two input vectors are not of the same size, there is a
0172     // logic error in the framework code that called this.
0173     // constructor.
0174     assert(numElements == helpers.size());
0175 
0176     items_.reserve(numElements);
0177     vPtrs_.reserve(numElements);
0178     for (std::vector<void const*>::size_type i = 0; i < pointers.size(); ++i) {
0179       void const* p = pointers[i];
0180       auto const& h = helpers[i];
0181       items_.push_back(static_cast<pointer>(p));
0182       if (nullptr != p) {
0183         vPtrs_.push_back(Ptr<T>(h.first, static_cast<T const*>(p), h.second));
0184       } else if (getter != nullptr) {
0185         vPtrs_.push_back(Ptr<T>(h.first, h.second, getter));
0186       } else {
0187         vPtrs_.push_back(Ptr<T>(h.first, nullptr, h.second));
0188       }
0189     }
0190   }
0191 
0192   template <typename T>
0193   inline void View<T>::swap(View& other) {
0194     this->ViewBase::swap(other);
0195     items_.swap(other.items_);
0196     vPtrs_.swap(other.vPtrs_);
0197   }
0198 
0199   template <typename T>
0200   inline typename View<T>::size_type View<T>::capacity() const {
0201     return items_.capacity();
0202   }
0203 
0204   template <typename T>
0205   inline typename View<T>::const_iterator View<T>::begin() const {
0206     return items_.begin();
0207   }
0208 
0209   template <typename T>
0210   inline typename View<T>::const_iterator View<T>::end() const {
0211     return items_.end();
0212   }
0213 
0214   template <typename T>
0215   inline typename View<T>::const_reverse_iterator View<T>::rbegin() const {
0216     return items_.rbegin();
0217   }
0218 
0219   template <typename T>
0220   inline typename View<T>::const_reverse_iterator View<T>::rend() const {
0221     return items_.rend();
0222   }
0223 
0224   template <typename T>
0225   inline typename View<T>::size_type View<T>::size() const {
0226     return items_.size();
0227   }
0228 
0229   template <typename T>
0230   inline typename View<T>::size_type View<T>::max_size() const {
0231     return items_.max_size();
0232   }
0233 
0234   template <typename T>
0235   inline bool View<T>::empty() const {
0236     return items_.empty();
0237   }
0238 
0239   template <typename T>
0240   inline typename View<T>::const_reference View<T>::at(size_type pos) const {
0241     return *items_.at(pos);
0242   }
0243 
0244   template <typename T>
0245   inline typename View<T>::const_reference View<T>::operator[](size_type pos) const {
0246     return *items_[pos];
0247   }
0248 
0249   template <typename T>
0250   inline RefToBase<T> View<T>::refAt(size_type i) const {
0251     //NOTE: considered creating a special BaseHolder for edm::Ptr.
0252     // But the IndirectHolder and RefHolder would still be needed
0253     // for other reasons. To reduce the number of dictionaries needed
0254     // we avoid using a more efficient BaseHolder.
0255     return RefToBase<T>(std::unique_ptr<reftobase::BaseHolder<T>>{new reftobase::IndirectHolder<T>{
0256         std::unique_ptr<reftobase::RefHolder<edm::Ptr<T>>>{new reftobase::RefHolder<Ptr<T>>{ptrAt(i)}}}});
0257   }
0258 
0259   template <typename T>
0260   inline Ptr<T> View<T>::ptrAt(size_type i) const {
0261     return vPtrs_[i];
0262   }
0263 
0264   template <typename T>
0265   inline std::vector<Ptr<T>> const& View<T>::ptrs() const {
0266     return vPtrs_;
0267   }
0268 
0269   template <typename T>
0270   inline typename View<T>::const_reference View<T>::front() const {
0271     return *items_.front();
0272   }
0273 
0274   template <typename T>
0275   inline typename View<T>::const_reference View<T>::back() const {
0276     return *items_.back();
0277   }
0278 
0279   // The following is for testing only.
0280   template <typename T>
0281   inline void View<T>::fill_from_range(T* first, T* last, View& output) {
0282     output.items_.resize(std::distance(first, last));
0283     for (typename View<T>::size_type i = 0; first != last; ++i, ++first)
0284       output.items_[i] = first;
0285   }
0286 
0287   template <typename T>
0288   std::unique_ptr<ViewBase> View<T>::doClone() const {
0289     return std::unique_ptr<ViewBase>{new View(*this)};
0290   }
0291 
0292   template <typename T>
0293   inline bool operator==(View<T> const& lhs, View<T> const& rhs) {
0294     return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
0295   }
0296 
0297   template <typename T>
0298   inline bool operator!=(View<T> const& lhs, View<T> const& rhs) {
0299     return !(lhs == rhs);
0300   }
0301 
0302   template <typename T>
0303   inline bool operator<(View<T> const& lhs, View<T> const& rhs) {
0304     return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
0305   }
0306 
0307   template <typename T>
0308   inline bool operator<=(View<T> const& lhs, View<T> const& rhs) {
0309     return !(rhs < lhs);
0310   }
0311 
0312   template <typename T>
0313   inline bool operator>(View<T> const& lhs, View<T> const& rhs) {
0314     return rhs < lhs;
0315   }
0316 
0317   template <typename T>
0318   inline bool operator>=(View<T> const& lhs, View<T> const& rhs) {
0319     return !(lhs < rhs);
0320   }
0321 
0322   // Free swap function
0323   template <typename T>
0324   inline void swap(View<T>& lhs, View<T>& rhs) {
0325     lhs.swap(rhs);
0326   }
0327 }  // namespace edm
0328 
0329 #endif