00001 #ifndef DataFormats_PatCandidates_UserData_h 00002 #define DataFormats_PatCandidates_UserData_h 00003 00016 #include <string> 00017 #include <vector> 00018 #include <typeinfo> 00019 #include <cxxabi.h> 00020 #include <DataFormats/Common/interface/OwnVector.h> 00021 00022 00023 namespace pat { 00024 00025 class UserData { 00026 public: 00027 UserData() {} 00028 virtual ~UserData() {} 00029 00031 virtual UserData * clone() const = 0; 00032 00034 virtual const std::type_info & typeId() const = 0; 00036 virtual const std::string & typeName() const = 0; 00037 00039 /* I don't think there is an easy way to get it working with generic type T, 00040 barrying the use of ROOT::Reflex and all the edm::Ptr technicalities. 00041 I'd say we can live without polymorphic storage of polymorphic data */ 00042 template<typename T> const T * get() const { 00043 if (typeid(T) != typeId()) return 0; 00044 return static_cast<const T *>(data_()); 00045 } 00046 00049 // Really needed for CINT? I would really like to avoid this 00050 const void * bareData() const { return data_(); } 00051 00054 template<typename T> 00055 static std::auto_ptr<UserData> make(const T &value, bool transientOnly=false) ; 00056 00057 protected: 00059 virtual const void * data_ () const = 0; 00060 00061 private: 00062 static void checkDictionaries(const std::type_info &type) ; 00063 00064 }; 00065 00066 template<typename T> 00067 class UserHolder : public UserData { 00068 public: 00069 UserHolder() : obj_() {} 00070 UserHolder(const T &data) : obj_(data) {} 00072 virtual UserHolder<T> * clone() const { return new UserHolder<T>(*this); } 00074 virtual const std::type_info & typeId() const { return typeid(T); } 00076 virtual const std::string & typeName() const { return typeName_(); } 00077 protected: 00078 virtual const void * data_() const { return &obj_; } 00079 private: 00080 T obj_; 00081 static const std::string & typeName_() ; 00082 }; 00083 00084 typedef edm::OwnVector<pat::UserData> UserDataCollection; 00085 } 00086 00087 00088 template<typename T> 00089 std::auto_ptr<pat::UserData> pat::UserData::make(const T &value, bool transientOnly) { 00090 if (!transientOnly) { 00091 checkDictionaries(typeid(T)); 00092 checkDictionaries(typeid(pat::UserHolder<T>)); 00093 } 00094 return std::auto_ptr<UserData>(new pat::UserHolder<T>(value)); 00095 } 00096 00097 template<typename T> 00098 const std::string & pat::UserHolder<T>::typeName_() { 00099 static int status = 0; 00100 static const char * demangled = abi::__cxa_demangle(typeid(T).name(), 0, 0, &status); 00101 static const std::string name(status == 0 ? demangled : "[UNKNOWN]"); 00102 return name; 00103 } 00104 00105 #endif