CMS 3D CMS Logo

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