Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:04:56

0001 #ifndef DataFormats_PatCandidates_UserData_h
0002 #define DataFormats_PatCandidates_UserData_h
0003 
0004 /** \class    pat::UserData UserData.h "DataFormats/PatCandidates/interface/UserData.h"
0005  *
0006  *  \brief    Base class for data that users can add to pat objects
0007  *
0008  *  
0009  *
0010  *  \author   Sal Rappoccio
0011  *
0012  *  \version  $Id: UserData.h,v 1.01 
0013  *
0014  */
0015 
0016 #include <string>
0017 #include <vector>
0018 #include <typeinfo>
0019 #include "DataFormats/Common/interface/OwnVector.h"
0020 
0021 namespace pat {
0022 
0023   class UserData {
0024   public:
0025     UserData() {}
0026     virtual ~UserData() {}
0027 
0028     /// Necessary for deep copy in OwnVector
0029     virtual UserData *clone() const = 0;
0030 
0031     /// Concrete type of stored data
0032     virtual const std::type_info &typeId() const = 0;
0033     /// Human readable name of the concrete type of stored data
0034     virtual const std::string &typeName() const = 0;
0035 
0036     /// Extract data in a typesafe way. <T> must be the *concrete* type of the data.
0037     /*  I don't think there is an easy way to get it working with generic type T,
0038         barrying the use of ROOT::Reflex and all the edm::Ptr technicalities.
0039         I'd say we can live without polymorphic storage of polymorphic data */
0040     template <typename T>
0041     const T *get() const {
0042       if (typeid(T) != typeId())
0043         return nullptr;
0044       return static_cast<const T *>(data_());
0045     }
0046 
0047     /// Get the data as a void *, for CINT usage.
0048     /// COMPLETELY UNSUPPORTED, USE ONLY FOR DEBUGGING
0049     //  Really needed for CINT? I would really like to avoid this
0050     const void *bareData() const { return data_(); }
0051 
0052     /// Make a UserData pointer from some value, wrapping it appropriately.
0053     /// It will check for dictionaries, unless 'transientOnly' is true
0054     template <typename T>
0055     static std::unique_ptr<UserData> make(const T &value, bool transientOnly = false);
0056 
0057   protected:
0058     /// Get out the data (can't template non virtual functions)
0059     virtual const void *data_() const = 0;
0060     static std::string typeNameFor(std::type_info const &iInfo);
0061 
0062   private:
0063     static void checkDictionaries(const std::type_info &type);
0064   };
0065 
0066   template <typename T>
0067   class UserHolder : public UserData {
0068   public:
0069     UserHolder() : obj_() {}
0070     UserHolder(const T &data) : obj_(data) {}
0071     /// Clone
0072     UserHolder<T> *clone() const override { return new UserHolder<T>(*this); }
0073     /// Concrete type of stored data
0074     const std::type_info &typeId() const override { return typeid(T); }
0075     /// Human readable name of the concrete type of stored data
0076     const std::string &typeName() const override { return typeName_(); }
0077 
0078   protected:
0079     const void *data_() const override { return &obj_; }
0080 
0081   private:
0082     T obj_;
0083     static const std::string &typeName_();
0084   };
0085 
0086   typedef edm::OwnVector<pat::UserData> UserDataCollection;
0087 }  // namespace pat
0088 
0089 template <typename T>
0090 std::unique_ptr<pat::UserData> pat::UserData::make(const T &value, bool transientOnly) {
0091   if (!transientOnly) {
0092     checkDictionaries(typeid(T));
0093     checkDictionaries(typeid(pat::UserHolder<T>));
0094   }
0095   return std::unique_ptr<UserData>(new pat::UserHolder<T>(value));
0096 }
0097 
0098 template <typename T>
0099 const std::string &pat::UserHolder<T>::typeName_() {
0100   static const std::string name(typeNameFor(typeid(T)));
0101   return name;
0102 }
0103 
0104 #endif