CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/DataFormats/Common/interface/Wrapper.h

Go to the documentation of this file.
00001 #ifndef DataFormats_Common_Wrapper_h
00002 #define DataFormats_Common_Wrapper_h
00003 
00004 /*----------------------------------------------------------------------
00005 
00006 Wrapper: A template wrapper around EDProducts to hold the product ID.
00007 
00008 ----------------------------------------------------------------------*/
00009 
00010 #include "DataFormats/Common/interface/EDProduct.h"
00011 #include "DataFormats/Common/interface/PtrVector.h"
00012 #include "DataFormats/Common/interface/RefVectorHolder.h"
00013 #include "DataFormats/Common/interface/traits.h"
00014 #include "FWCore/Utilities/interface/EDMException.h"
00015 #include "DataFormats/Common/interface/fwd_setPtr.h"
00016 #include "DataFormats/Common/interface/fwd_fillPtrVector.h"
00017 
00018 #include "boost/mpl/if.hpp"
00019 
00020 #include <algorithm>
00021 #include <memory>
00022 #include <string>
00023 #include <typeinfo>
00024 
00025 namespace edm {
00026 
00027   template <typename T>
00028   class Wrapper : public EDProduct {
00029   public:
00030     typedef T value_type;
00031     typedef T wrapped_type;  // used with Reflex to identify Wrappers
00032     Wrapper() : EDProduct(), present(false), obj() {}
00033     explicit Wrapper(std::auto_ptr<T> ptr);
00034     virtual ~Wrapper() {}
00035     T const* product() const {return (present ? &obj : 0);}
00036     T const* operator->() const {return product();}
00037 
00038     //these are used by FWLite
00039     static std::type_info const& productTypeInfo() { return typeid(T);}
00040     static std::type_info const& typeInfo() { return typeid(Wrapper<T>);}
00041 
00044     Wrapper(T*);
00045 
00046   private:
00047     virtual bool isPresent_() const {return present;}
00048     virtual std::type_info const& dynamicTypeInfo_() const { return typeid(T);}
00049 #ifndef __REFLEX__
00050     virtual bool isMergeable_() const;
00051     virtual bool mergeProduct_(EDProduct const* newProduct);
00052     virtual bool hasIsProductEqual_() const;
00053     virtual bool isProductEqual_(EDProduct const* newProduct) const;
00054 #endif
00055     virtual void do_fillView(ProductID const& id,
00056                              std::vector<void const*>& pointers,
00057                              helper_vector_ptr& helpers) const;
00058     virtual void do_setPtr(std::type_info const& iToType,
00059                            unsigned long iIndex,
00060                            void const*& oPtr) const;
00061     virtual void do_fillPtrVector(std::type_info const& iToType,
00062                                   std::vector<unsigned long> const& iIndices,
00063                                   std::vector<void const*>& oPtr) const;
00064 
00065     // We wish to disallow copy construction and assignment.
00066     // We make the copy constructor and assignment operator private.
00067     Wrapper(Wrapper<T> const& rh); // disallow copy construction
00068     Wrapper<T> & operator=(Wrapper<T> const&); // disallow assignment
00069 
00070     bool present;
00071     //   T const obj;
00072     T obj;
00073   };
00074 
00075 } //namespace edm
00076 
00077 #include "DataFormats/Common/interface/Ref.h"
00078 
00079 namespace edm {
00080 
00081   template <typename T>
00082   struct DoFillView {
00083     void operator()(T const& obj,
00084                     ProductID const& id,
00085                     std::vector<void const*>& pointers,
00086                     helper_vector_ptr & helpers) const;
00087   };
00088 
00089   template <typename T>
00090   struct DoNotFillView {
00091     void operator()(T const&,
00092                     ProductID const&,
00093                     std::vector<void const*>&,
00094                     helper_vector_ptr&) const {
00095       Exception::throwThis(errors::ProductDoesNotSupportViews,
00096         "The product type ",
00097         typeid(T).name(),
00098         "\ndoes not support Views\n");
00099     }
00100   };
00101 
00102   template <typename T>
00103   inline
00104   void Wrapper<T>::do_fillView(ProductID const& id,
00105                                std::vector<void const*>& pointers,
00106                                helper_vector_ptr& helpers) const {
00107     typename boost::mpl::if_c<has_fillView<T>::value,
00108     DoFillView<T>,
00109     DoNotFillView<T> >::type maybe_filler;
00110     maybe_filler(obj, id, pointers, helpers);
00111   }
00112 
00113 
00114   template <typename T>
00115   struct DoSetPtr {
00116     void operator()(T const& obj,
00117                     std::type_info const& iToType,
00118                     unsigned long iIndex,
00119                     void const*& oPtr) const;
00120     void operator()(T const& obj,
00121                     std::type_info const& iToType,
00122                     std::vector<unsigned long> const& iIndex,
00123                     std::vector<void const*>& oPtr) const;
00124   };
00125 
00126   template <typename T>
00127   struct DoNotSetPtr {
00128     void operator()(T const&,
00129                     std::type_info const&,
00130                     unsigned long,
00131                     void const*& oPtr) const {
00132       Exception::throwThis(errors::ProductDoesNotSupportPtr,
00133         "The product type ",
00134         typeid(T).name(),
00135         "\ndoes not support edm::Ptr\n");
00136     }
00137     void operator()(T const& obj,
00138                     std::type_info const& iToType,
00139                     std::vector<unsigned long> const& iIndex,
00140                     std::vector<void const*>& oPtr) const {
00141       Exception::throwThis(errors::ProductDoesNotSupportPtr,
00142         "The product type ",
00143         typeid(T).name(),
00144         "\ndoes not support edm::PtrVector\n");
00145     }
00146   };
00147 
00148   template <typename T>
00149   inline
00150   void Wrapper<T>::do_setPtr(std::type_info const& iToType,
00151                              unsigned long iIndex,
00152                              void const*& oPtr) const {
00153     typename boost::mpl::if_c<has_setPtr<T>::value,
00154     DoSetPtr<T>,
00155     DoNotSetPtr<T> >::type maybe_filler;
00156     maybe_filler(this->obj,iToType,iIndex,oPtr);
00157   }
00158 
00159   template <typename T>
00160   void Wrapper<T>::do_fillPtrVector(std::type_info const& iToType,
00161                                        std::vector<unsigned long> const& iIndices,
00162                                        std::vector<void const*>& oPtr) const {
00163     typename boost::mpl::if_c<has_setPtr<T>::value,
00164     DoSetPtr<T>,
00165     DoNotSetPtr<T> >::type maybe_filler;
00166     maybe_filler(this->obj,iToType,iIndices,oPtr);
00167   }
00168 
00169   // This is an attempt to optimize for speed, by avoiding the copying
00170   // of large objects of type T. In this initial version, we assume
00171   // that for any class having a 'swap' member function should call
00172   // 'swap' rather than copying the object.
00173 
00174   template <typename T>
00175   struct DoSwap {
00176     void operator()(T& a, T& b) { a.swap(b); }
00177   };
00178 
00179   template <typename T>
00180   struct DoAssign {
00181     void operator()(T& a, T& b) { a = b; }
00182   };
00183 
00184 #ifndef __REFLEX__
00185   template <typename T>
00186   struct IsMergeable {
00187     bool operator()(T const& a) const { return true; }
00188   };
00189 
00190   template <typename T>
00191   struct IsNotMergeable {
00192     bool operator()(T const& a) const { return false; }
00193   };
00194 
00195   template <typename T>
00196   struct DoMergeProduct {
00197     bool operator()(T& a, T const& b) { return a.mergeProduct(b); }
00198   };
00199 
00200   template <typename T>
00201   struct DoNotMergeProduct {
00202     bool operator()(T& a, T const& b) { return true; }
00203   };
00204 
00205   template <typename T>
00206   struct DoHasIsProductEqual {
00207     bool operator()(T const& a) const { return true; }
00208   };
00209 
00210   template <typename T>
00211   struct DoNotHasIsProductEqual {
00212     bool operator()(T const& a) const { return false; }
00213   };
00214 
00215   template <typename T>
00216   struct DoIsProductEqual {
00217     bool operator()(T const& a, T const& b) const { return a.isProductEqual(b); }
00218   };
00219 
00220   template <typename T>
00221   struct DoNotIsProductEqual {
00222     bool operator()(T const& a, T const& b) const { return true; }
00223   };
00224 #endif
00225 
00226   //------------------------------------------------------------
00227   // Metafunction support for compile-time selection of code used in
00228   // Wrapper constructor
00229   //
00230 
00231   namespace detail {
00232     typedef char (& no_tag)[1]; // type indicating FALSE
00233     typedef char (& yes_tag)[2]; // type indicating TRUE
00234 
00235     // Definitions for the following struct and function templates are
00236     // not needed; we only require the declarations.
00237     template <typename T, void (T::*)(T&)>  struct swap_function;
00238     template <typename T> no_tag  has_swap_helper(...);
00239     template <typename T> yes_tag has_swap_helper(swap_function<T, &T::swap> * dummy);
00240 
00241     template<typename T>
00242     struct has_swap_function {
00243       static bool const value =
00244         sizeof(has_swap_helper<T>(0)) == sizeof(yes_tag);
00245     };
00246 
00247 #ifndef __REFLEX__
00248     template <typename T, bool (T::*)(T const&)>  struct mergeProduct_function;
00249     template <typename T> no_tag  has_mergeProduct_helper(...);
00250     template <typename T> yes_tag has_mergeProduct_helper(mergeProduct_function<T, &T::mergeProduct> * dummy);
00251 
00252     template<typename T>
00253     struct has_mergeProduct_function {
00254       static bool const value =
00255         sizeof(has_mergeProduct_helper<T>(0)) == sizeof(yes_tag);
00256     };
00257 
00258     template <typename T, bool (T::*)(T const&) const> struct isProductEqual_function;
00259     template <typename T> no_tag  has_isProductEqual_helper(...);
00260     template <typename T> yes_tag has_isProductEqual_helper(isProductEqual_function<T, &T::isProductEqual> * dummy);
00261 
00262     template<typename T>
00263     struct has_isProductEqual_function {
00264       static bool const value =
00265         sizeof(has_isProductEqual_helper<T>(0)) == sizeof(yes_tag);
00266     };
00267 #endif
00268   }
00269 
00270   template <typename T>
00271   Wrapper<T>::Wrapper(std::auto_ptr<T> ptr) :
00272     EDProduct(),
00273     present(ptr.get() != 0),
00274     obj() {
00275     if (present) {
00276       // The following will call swap if T has such a function,
00277       // and use assignment if T has no such function.
00278       typename boost::mpl::if_c<detail::has_swap_function<T>::value,
00279         DoSwap<T>,
00280         DoAssign<T> >::type swap_or_assign;
00281       swap_or_assign(obj, *ptr);
00282     }
00283   }
00284 
00285   template <typename T>
00286   Wrapper<T>::Wrapper(T* ptr) :
00287   EDProduct(),
00288   present(ptr != 0),
00289   obj() {
00290      std::auto_ptr<T> temp(ptr);
00291      if (present) {
00292         // The following will call swap if T has such a function,
00293         // and use assignment if T has no such function.
00294         typename boost::mpl::if_c<detail::has_swap_function<T>::value,
00295         DoSwap<T>,
00296         DoAssign<T> >::type swap_or_assign;
00297         swap_or_assign(obj, *ptr);
00298      }
00299 
00300   }
00301 
00302 #ifndef __REFLEX__
00303   template <typename T>
00304   bool Wrapper<T>::isMergeable_() const {
00305     typename boost::mpl::if_c<detail::has_mergeProduct_function<T>::value,
00306       IsMergeable<T>,
00307       IsNotMergeable<T> >::type is_mergeable;
00308     return is_mergeable(obj);
00309   }
00310 
00311   template <typename T>
00312   bool Wrapper<T>::mergeProduct_(EDProduct const* newProduct) {
00313     Wrapper<T> const* wrappedNewProduct = dynamic_cast<Wrapper<T> const*>(newProduct);
00314     if (wrappedNewProduct == 0) return false;
00315     typename boost::mpl::if_c<detail::has_mergeProduct_function<T>::value,
00316       DoMergeProduct<T>,
00317       DoNotMergeProduct<T> >::type merge_product;
00318     return merge_product(obj, wrappedNewProduct->obj);
00319   }
00320 
00321   template <typename T>
00322   bool Wrapper<T>::hasIsProductEqual_() const {
00323     typename boost::mpl::if_c<detail::has_isProductEqual_function<T>::value,
00324       DoHasIsProductEqual<T>,
00325       DoNotHasIsProductEqual<T> >::type has_is_equal;
00326     return has_is_equal(obj);
00327   }
00328 
00329   template <typename T>
00330   bool Wrapper<T>::isProductEqual_(EDProduct const* newProduct) const {
00331     Wrapper<T> const* wrappedNewProduct = dynamic_cast<Wrapper<T> const*>(newProduct);
00332     if (wrappedNewProduct == 0) return false;
00333     typename boost::mpl::if_c<detail::has_isProductEqual_function<T>::value,
00334       DoIsProductEqual<T>,
00335       DoNotIsProductEqual<T> >::type is_equal;
00336     return is_equal(obj, wrappedNewProduct->obj);
00337   }
00338 #endif
00339 }
00340 
00341 #include "DataFormats/Common/interface/RefVector.h"
00342 #include "DataFormats/Common/interface/RefToBaseVector.h"
00343 
00344 namespace edm {
00345   namespace helpers {
00346     template<typename T>
00347     struct ViewFiller {
00348       static void fill(T const& obj,
00349                        ProductID const& id,
00350                        std::vector<void const*>& pointers,
00351                        helper_vector_ptr & helpers) {
00353         typedef Ref<T> ref;
00354         typedef RefVector<T, typename ref::value_type, typename ref::finder_type> ref_vector;
00355         helpers = helper_vector_ptr(new reftobase::RefVectorHolder<ref_vector>);
00356         // fillView is the name of an overload set; each concrete
00357         // collection T should supply a fillView function, in the same
00358         // namespace at that in which T is defined, or in the 'edm'
00359         // namespace.
00360         fillView(obj, id, pointers, * helpers);
00361         assert(pointers.size() == helpers->size());
00362      }
00363     };
00364 
00365     template<typename T>
00366     struct ViewFiller<RefToBaseVector<T> > {
00367       static void fill(RefToBaseVector<T> const& obj,
00368                        ProductID const& id,
00369                        std::vector<void const*>& pointers,
00370                        helper_vector_ptr & helpers) {
00371         std::auto_ptr<helper_vector> h = obj.vectorHolder();
00372         if(h.get() != 0) {
00373           pointers.reserve(h->size());
00374           // NOTE: the following implementation has unusual signature!
00375           fillView(obj, pointers);
00376           helpers = helper_vector_ptr(h);
00377         }
00378       }
00379     };
00380 
00381     template<typename T>
00382     struct ViewFiller<PtrVector<T> > {
00383       static void fill(PtrVector<T> const& obj,
00384                        ProductID const& id,
00385                        std::vector<void const*>& pointers,
00386                        helper_vector_ptr & helpers) {
00387         std::auto_ptr<helper_vector> h(new reftobase::RefVectorHolder<PtrVector<T> >(obj));
00388         if(h.get() != 0) {
00389           pointers.reserve(obj.size());
00390           // NOTE: the following implementation has unusual signature!
00391           fillView(obj, pointers);
00392           helpers = helper_vector_ptr(h);
00393         }
00394       }
00395     };
00396 
00397     template<typename T>
00398       struct PtrSetter {
00399         static void set(T const& obj,
00400                          std::type_info const& iToType,
00401                          unsigned long iIndex,
00402                          void const*& oPtr) {
00403           // setPtr is the name of an overload set; each concrete
00404           // collection T should supply a fillView function, in the same
00405           // namespace at that in which T is defined, or in the 'edm'
00406           // namespace.
00407           setPtr(obj, iToType, iIndex, oPtr);
00408         }
00409 
00410         static void fill(T const& obj,
00411                          std::type_info const& iToType,
00412                          std::vector<unsigned long> const& iIndex,
00413                          std::vector<void const*>& oPtr) {
00414           // fillPtrVector is the name of an overload set; each concrete
00415           // collection T should supply a fillPtrVector function, in the same
00416           // namespace at that in which T is defined, or in the 'edm'
00417           // namespace.
00418           fillPtrVector(obj, iToType, iIndex, oPtr);
00419         }
00420       };
00421   }
00422 
00423   template <typename T>
00424   void DoFillView<T>::operator()(T const& obj,
00425                                  ProductID const& id,
00426                                  std::vector<void const*>& pointers,
00427                                  helper_vector_ptr& helpers) const {
00428     helpers::ViewFiller<T>::fill(obj, id, pointers, helpers);
00429   }
00430 
00431   template <typename T>
00432   void DoSetPtr<T>::operator()(T const& obj,
00433                                std::type_info const& iToType,
00434                                unsigned long iIndex,
00435                                void const*& oPtr) const {
00436     helpers::PtrSetter<T>::set(obj, iToType, iIndex, oPtr);
00437   }
00438 
00439   template <typename T>
00440   void DoSetPtr<T>::operator()(T const& obj,
00441                                std::type_info const& iToType,
00442                                std::vector<unsigned long> const& iIndices,
00443                                std::vector<void const*>& oPtr) const {
00444     helpers::PtrSetter<T>::fill(obj, iToType, iIndices, oPtr);
00445   }
00446 
00447 }
00448 
00449 #include "DataFormats/Common/interface/FillView.h"
00450 #include "DataFormats/Common/interface/setPtr.h"
00451 #include "DataFormats/Common/interface/fillPtrVector.h"
00452 
00453 #endif