CMS 3D CMS Logo

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