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