CMS 3D CMS Logo

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