CMS 3D CMS Logo

AssociationVector.h

Go to the documentation of this file.
00001 #ifndef DataFormats_Common_AssociationVector_h
00002 #define DataFormats_Common_AssociationVector_h
00003 /* class edm::AssociationVector<CKey, CVal>
00004  *
00005  * adds to a std::vector<CVal> a edm::RefProd<CKey>, in such a way
00006  * that, assuming that the CVal and CKey collections have the same
00007  * size and are properly ordered, the two collections can be
00008  * in one-to-one correspondance
00009  *
00010  * \author Luca Lista, INFN
00011  *
00012  * \version $Revision: 1.28 $
00013  */
00014 
00015 #include "FWCore/Utilities/interface/EDMException.h"
00016 
00017 #include "DataFormats/Common/interface/traits.h"
00018 #include "DataFormats/Common/interface/EDProduct.h"
00019 #include "DataFormats/Common/interface/RefProd.h"
00020 #include "DataFormats/Common/interface/RefToBaseProd.h"
00021 #include "DataFormats/Common/interface/Ref.h"
00022 #include "DataFormats/Common/interface/RefToBase.h"
00023 #include "DataFormats/Common/interface/FillView.h"
00024 
00025 #include "DataFormats/Provenance/interface/ProductID.h"
00026 
00027 #include "boost/static_assert.hpp"
00028 #include "boost/type_traits/is_same.hpp"
00029 
00030 namespace edm {
00031   namespace helper {
00032 
00033     struct AssociationIdenticalKeyReference {
00034       template<typename T>
00035       static const T & get( const T & t, edm::ProductID ) { return t; }
00036     };
00037     
00038     template<typename T>
00039     struct AssociationKeyReferenceTrait {
00040       typedef AssociationIdenticalKeyReference type;
00041     };
00042 
00043     template<typename REFPROD>
00044     struct RefFromRefProdTrait { };
00045 
00046     template<typename C>
00047     struct RefFromRefProdTrait<RefProd<C> > {
00048       typedef Ref<typename RefProd<C>::product_type> ref_type;
00049     };
00050 
00051     template<typename T>
00052     struct RefFromRefProdTrait<RefToBaseProd<T> > {
00053       typedef RefToBase<T> ref_type;
00054     };
00055   }
00056 
00057   template<typename KeyRefProd, typename CVal, 
00058     typename KeyRef = typename helper::RefFromRefProdTrait<KeyRefProd>::ref_type,
00059     typename SizeType = typename KeyRefProd::product_type::size_type,
00060     typename KeyReferenceHelper = typename helper::AssociationKeyReferenceTrait<KeyRef>::type>
00061   class AssociationVector {
00062     BOOST_STATIC_ASSERT( ( boost::is_same<SizeType, typename CVal::size_type>::value ) );
00063     typedef AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper> self;
00064 
00065   public:
00066     typedef KeyRefProd refprod_type;
00067     typedef typename KeyRefProd::product_type CKey;
00068     typedef SizeType size_type;
00069     typedef typename KeyRef::value_type key_type;
00070     typedef typename std::pair<KeyRef, typename CVal::value_type> value_type;
00071     typedef std::vector<value_type> transient_vector_type;
00072     typedef const value_type & const_reference;
00073     AssociationVector();
00074     AssociationVector(const KeyRefProd & ref, const CKey * = 0);
00075     AssociationVector(const AssociationVector &);
00076     ~AssociationVector();
00077     
00078     size_type size() const;
00079     bool empty() const;
00080     const_reference operator[](size_type n) const;
00081     typename CVal::const_reference operator[](const KeyRef & k) const;
00082     typename CVal::reference operator[](const KeyRef & k);
00083     
00084     self & operator=(const self & );
00085     
00086     void clear();
00087     void swap(self & other);
00088     const KeyRefProd & keyProduct() const { return ref_; }
00089     KeyRef key(size_type i) const { return KeyRef(ref_, i); }
00090     const typename CVal::value_type value(size_type i) const { return data_[ i ]; }
00091     void setValue(size_type i, const typename CVal::value_type & val );
00092     void fillView(ProductID const& id,
00093                   std::vector<void const*>& pointers,
00094                   helper_vector& helpers) const;
00095 
00096     typedef typename transient_vector_type::const_iterator const_iterator;
00097 
00098     const_iterator begin() const { return transientVector().begin(); } 
00099     const_iterator end() const { return transientVector().end(); } 
00100 
00101   private:
00102     CVal data_;
00103     KeyRefProd ref_;
00104     mutable transient_vector_type transientVector_;
00105     mutable bool fixed_;
00106     const transient_vector_type & transientVector() const { fixup(); return transientVector_; }
00107     void fixup() const;
00108   };
00109   
00110   template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00111   inline AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::AssociationVector() : 
00112     data_(), ref_(), transientVector_(), fixed_(false)  { }
00113   
00114   template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00115   inline AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::AssociationVector(const KeyRefProd & ref,
00116                                                                                                       const CKey * coll) : 
00117     data_(coll == 0 ? ref->size() : coll->size()), ref_(ref), 
00118     transientVector_(coll == 0 ? ref->size() : coll->size()), fixed_(true) { }
00119   
00120   template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00121   inline AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::
00122     AssociationVector(const AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper> & o) : 
00123     data_(o.data_), ref_(o.ref_), transientVector_(o.transientVector_), fixed_(o.fixed_) { }
00124   
00125   template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00126   inline AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::~AssociationVector() { }
00127 
00128   template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00129   inline typename AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::const_reference 
00130   AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::operator[](size_type n) const { 
00131     return transientVector()[ n ]; 
00132   }
00133   
00134   template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00135   inline typename CVal::const_reference
00136   AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::operator[]( const KeyRef & k ) const {
00137     KeyRef keyRef = KeyReferenceHelper::get( k, ref_.id() );
00138     if ( keyRef.id() == ref_.id() ) 
00139       return data_[ keyRef.key() ];
00140     else 
00141       throw edm::Exception(edm::errors::InvalidReference) 
00142         << "AssociationVector: trying to use [] operator passing a reference"
00143         << " with the wrong product id (i.e.: pointing to the wrong collection)";
00144   }
00145 
00146   template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00147   inline typename CVal::reference
00148   AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::operator[]( const KeyRef & k ) {
00149     KeyRef keyRef = KeyReferenceHelper::get( k, ref_.id() );
00150     fixed_ = false;
00151     if ( keyRef.id() == ref_.id() ) 
00152       return data_[ keyRef.key() ];
00153     else 
00154       throw edm::Exception(edm::errors::InvalidReference) 
00155         << "AssociationVector: trying to use [] operator passing a reference"
00156         << " with the wrong product id (i.e.: pointing to the wrong collection)";
00157   }
00158 
00159   template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00160   inline AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper> & 
00161   AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::operator=(const self & o) {
00162     data_ = o.data_;
00163     ref_ = o.ref_;
00164     fixed_ = false;
00165     return * this;
00166   }
00167 
00168   template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00169   inline void AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::setValue(size_type i, const typename CVal::value_type & val ) { 
00170     data_[ i ] = val; 
00171     KeyRef ref(ref_, i);
00172     transientVector_[ i ].first = ref;
00173     transientVector_[ i ].second = data_[ i ];
00174   }  
00175   
00176   template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00177   inline typename AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::size_type 
00178     AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::size() const {
00179     return data_.size();
00180   }
00181   
00182   template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00183   inline bool AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::empty() const {
00184     return data_.empty();
00185   }
00186   
00187   template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00188   inline void AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::clear() {
00189     data_.clear();
00190     transientVector_.clear();
00191     ref_ = KeyRefProd();
00192     fixed_ = true;
00193   }
00194 
00195   template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00196   inline void AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::swap(self & other) {
00197     data_.swap(other.data_);
00198     transientVector_.swap(other.transientVector_);
00199     ref_.swap( other.ref_);
00200     std::swap(fixed_, other.fixed_);
00201   }
00202 
00203   template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00204   inline void AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::fixup() const { 
00205     if (!fixed_) {
00206       fixed_ = true;
00207       transientVector_.resize( size() );
00208       for( size_type i = 0; i != size(); ++ i ) {
00209         transientVector_[ i ] = std::make_pair( KeyRef(ref_, i), data_[ i ] );
00210       }
00211     }
00212   }
00213 
00214   template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00215   void AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::fillView(ProductID const& id,
00216                                                                                           std::vector<void const*>& pointers, 
00217                                                                                           helper_vector& helpers) const
00218   {
00219     detail::reallyFillView(*this, id, pointers, helpers);
00220 //     pointers.reserve(this->size());
00221 //     for(typename CVal::const_iterator i=data_.begin(), e=data_.end(); i!=e; ++i)
00222 //       pointers.push_back(&(*i));
00223 //     // helpers is not yet filled in.
00224 //     //throw edm::Exception(errors::UnimplementedFeature, "AssociationVector<T>::fillView(...)");
00225   }
00226 
00227   template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00228   inline void swap(AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper> & a, 
00229                    AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper> & b) {
00230     a.swap(b);
00231   }
00232 
00233   //----------------------------------------------------------------------
00234   //
00235   // Free function template to support creation of Views.
00236 
00237   template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00238   inline
00239   void
00240   fillView(AssociationVector<KeyRefProd,CVal, KeyRef, SizeType, KeyReferenceHelper> const& obj,
00241            ProductID const& id,
00242            std::vector<void const*>& pointers,
00243            helper_vector& helpers) {
00244     obj.fillView(id, pointers, helpers);
00245   }
00246 
00247   template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00248   struct has_fillView<edm::AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper> > {
00249     static bool const value = true;
00250   };
00251 
00252 }
00253 
00254 #endif

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