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
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
00078
00079 Wrapper(Wrapper<T> const& rh);
00080 Wrapper<T>& operator=(Wrapper<T> const&);
00081
00082 bool present;
00083
00084 T obj;
00085 };
00086
00087 }
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
00120
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& ,
00146 std::type_info const& ,
00147 unsigned long ,
00148 void const*& ) 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& ,
00155 std::type_info const& ,
00156 std::vector<unsigned long> const& ,
00157 std::vector<void const*>& ) 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
00187
00188
00189
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
00245
00246
00247
00248 namespace detail {
00249 typedef char (& no_tag)[1];
00250 typedef char (& yes_tag)[2];
00251
00252
00253
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
00293
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
00308
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
00368
00369
00370
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
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
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
00415
00416
00417
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
00426
00427
00428
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