00001 #ifndef DataFormats_Common_Wrapper_h
00002 #define DataFormats_Common_Wrapper_h
00003
00004
00005
00006
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;
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
00040 static std::type_info const& productTypeInfo() { return typeid(T);}
00041 static std::type_info const& typeInfo() { return typeid(Wrapper<T>);}
00042
00043
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
00077
00078 Wrapper(Wrapper<T> const& rh);
00079 Wrapper<T>& operator=(Wrapper<T> const&);
00080
00081 bool present;
00082
00083 T obj;
00084 };
00085
00086 }
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
00119
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& ,
00145 std::type_info const& ,
00146 unsigned long ,
00147 void const*& ) 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& ,
00154 std::type_info const& ,
00155 std::vector<unsigned long> const& ,
00156 std::vector<void const*>& ) 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
00186
00187
00188
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
00244
00245
00246
00247 namespace detail {
00248 typedef char (& no_tag)[1];
00249 typedef char (& yes_tag)[2];
00250
00251
00252
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
00292
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
00307
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
00367
00368
00369
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
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
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
00414
00415
00416
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
00425
00426
00427
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