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