Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:53:04

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