Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:44:51

0001 //=========================================================================
0002 // ClassId.hh
0003 //
0004 // Class identifier for I/O operations. Contains class name and version
0005 // number. For templates, it should also contain version numbers of all
0006 // template parameter classes.
0007 //
0008 // I. Volobouev
0009 // September 2010
0010 //=========================================================================
0011 
0012 #ifndef GENERS_CLASSID_HH_
0013 #define GENERS_CLASSID_HH_
0014 
0015 #include <iostream>
0016 #include <string>
0017 #include <vector>
0018 
0019 namespace gs {
0020   class ClassId {
0021   public:
0022     // Generic constructor using a prefix (which is usually
0023     // a class name) and a version number
0024     inline ClassId(const char *prefix, const unsigned version, const bool isPtr = false) {
0025       initialize(prefix, version, isPtr);
0026     }
0027 
0028     // Generic constructor using a prefix (which is usually
0029     // a class name) and a version number
0030     inline ClassId(const std::string &prefix, const unsigned version, const bool isPtr = false) {
0031       initialize(prefix.c_str(), version, isPtr);
0032     }
0033 
0034     // Use the following constructor in the "classId()" methods
0035     // of user-developed classes.
0036     //
0037     // Implementation note: it is possible to "specialize"
0038     // this constructor by delegating the actual job to the
0039     // "ClassIdSpecialization". Then we would be able to create
0040     // class ids for built-in and user types in a unified
0041     // way. This, however, would incur a performance hit
0042     // due to the necessity of making another ClassId and
0043     // copying the result into the internals of the new object.
0044     // This performance hit was deemed significant. If you
0045     // need a universal way to create class ids at some
0046     // point in your code, use the "itemId" method instead
0047     // (this may or may not incur a performance hit, depending
0048     // on what exactly the compiler does).
0049     template <class T>
0050     inline ClassId(const T &) {
0051       initialize(T::classname(), T::version(), false);
0052     }
0053 
0054     // Constructor from the class id represented by a string
0055     explicit ClassId(const std::string &id);
0056 
0057     // Use the following constructor in "read" functions.
0058     // Dummy argument "reading" is needed in order to generate
0059     // a distinct function signature (otherwise the templated
0060     // constructor can win).
0061     ClassId(std::istream &in, int reading);
0062 
0063     // Use the following pseudo-constructor in static "read"
0064     // methods in case a type check is desired. It has to be
0065     // made static because constructor without any arguments
0066     // can not be a template. Also, this is the way to construct
0067     // class ids for built-in types (there is no way to specialize
0068     // member methods).
0069     template <class T>
0070     static ClassId makeId();
0071 
0072     // "Universal" item id which also works for built-in types
0073     template <class T>
0074     static ClassId itemId(const T &);
0075 
0076     // Inspectors for the class name and version number
0077     inline const std::string &name() const { return name_; }
0078     inline unsigned version() const { return version_; }
0079 
0080     // Is this class a pointer for I/O purposes?
0081     inline bool isPointer() const { return isPtr_; }
0082 
0083     // The following function should return a unique class id string
0084     // which takes version number into account
0085     inline const std::string &id() const { return id_; }
0086 
0087     // The following checks if the class name corresponds to
0088     // a template (using the standard manner of class name forming)
0089     bool isTemplate() const;
0090 
0091     // The following function fills the vector with class template
0092     // parameters (if the class is not a template, the vector is
0093     // cleared). Due to the manner in which things are used in this
0094     // package, the result is actually a vector of (vectors of size 1).
0095     void templateParameters(std::vector<std::vector<ClassId>> *p) const;
0096 
0097     // Function to write this object out. Returns "true" on success.
0098     bool write(std::ostream &of) const;
0099 
0100     // Comparison operators
0101     inline bool operator==(const ClassId &r) const { return id_ == r.id_; }
0102     inline bool operator!=(const ClassId &r) const { return !(*this == r); }
0103     inline bool operator<(const ClassId &r) const { return id_ < r.id_; }
0104     inline bool operator>(const ClassId &r) const { return id_ > r.id_; }
0105 
0106     // Modify the version number
0107     void setVersion(unsigned newVersion);
0108 
0109     // The following methods verify that the id/classname/version
0110     // of this object are equal to those of the argument and throw
0111     // "gs::IOInvalidArgument" exception if this is not so
0112     void ensureSameId(const ClassId &id) const;
0113     void ensureSameName(const ClassId &id) const;
0114     void ensureSameVersion(const ClassId &id) const;
0115 
0116     // The following method ensures that the version number of this
0117     // class id is within certain range [min, max], with both limits
0118     // allowed. "gs::IOInvalidArgument" exception is thrown if this
0119     // is not so.
0120     void ensureVersionInRange(unsigned min, unsigned max) const;
0121 
0122     // Sometimes one really needs to make a placeholder class id...
0123     // This is a dangerous function: the code using ClassId class
0124     // will normally assume that a ClassId object is always in a valid
0125     // state. Invalid class ids can be distinguished by their empty
0126     // class names (i.e., name().empty() returns "true").
0127     static ClassId invalidId();
0128 
0129   private:
0130     ClassId();
0131 
0132     void initialize(const char *prefix, unsigned version, bool isPtr);
0133     bool makeName();
0134     bool makeVersion();
0135 
0136     std::string name_;
0137     std::string id_;
0138     unsigned version_;
0139     bool isPtr_;
0140 
0141     // Return "true" if the prefix is valid
0142     static bool validatePrefix(const char *prefix);
0143   };
0144 
0145   // Simple class id compatibility checkers for use as policy classes
0146   // in templated code
0147   struct SameClassId {
0148     inline static bool compatible(const ClassId &id1, const ClassId &id2) { return id1.name() == id2.name(); }
0149   };
0150 
0151   struct SameClassName {
0152     inline static bool compatible(const ClassId &id1, const ClassId &id2) { return id1 == id2; }
0153   };
0154 
0155   // Specialize the following template in order to be able to construct
0156   // ClassId for classes which do not implement static functions
0157   // "classname()" and "version()".
0158   template <class T>
0159   struct ClassIdSpecialization {
0160     inline static ClassId classId(const bool isPtr = false) { return ClassId(T::classname(), T::version(), isPtr); }
0161   };
0162 
0163   // Utility functions for naming template classes. The "nInclude"
0164   // argument tells us how many template parameters to include into
0165   // the generated template name. For example, use of
0166   //
0167   // template_class_name<X,Y>("myTemplate",1)
0168   //
0169   // will generate a class name which looks like myTemplate<X>, with
0170   // second template parameter omitted. While the result is equivalent
0171   // to invoking "template_class_name<X>("myTemplate")", having an
0172   // explicit limit is convenient for use from certain higher-level
0173   // functions. Note, however, that in the call with two template
0174   // parameters the class id specialization for Y must be available,
0175   // even though it is not used.
0176   //
0177   // This feature is sometimes helpful when certain template parameters
0178   // specify aspects of template behavior which have nothing to do
0179   // with object data contents and I/O. Typical example of such
0180   // a parameter is std::allocator of STL -- changing this to a custom
0181   // allocator will not affect serialized representation of an STL
0182   // container.
0183   //
0184   template <class T>
0185   std::string template_class_name(const char *templateName, unsigned nInclude = 1);
0186   template <class T>
0187   std::string template_class_name(const std::string &templateName, unsigned nInclude = 1);
0188   template <class T1, class T2>
0189   std::string template_class_name(const char *templateName, unsigned nInclude = 2);
0190   template <class T1, class T2>
0191   std::string template_class_name(const std::string &templateName, unsigned nInclude = 2);
0192   template <class T1, class T2, class T3>
0193   std::string template_class_name(const char *templateName, unsigned nInclude = 3);
0194   template <class T1, class T2, class T3>
0195   std::string template_class_name(const std::string &templateName, unsigned nInclude = 3);
0196   template <class T1, class T2, class T3, class T4>
0197   std::string template_class_name(const char *templateName, unsigned nInclude = 4);
0198   template <class T1, class T2, class T3, class T4>
0199   std::string template_class_name(const std::string &templateName, unsigned nInclude = 4);
0200   template <class T1, class T2, class T3, class T4, class T5>
0201   std::string template_class_name(const char *templateName, unsigned nInclude = 5);
0202   template <class T1, class T2, class T3, class T4, class T5>
0203   std::string template_class_name(const std::string &templateName, unsigned nInclude = 5);
0204   template <class T1, class T2, class T3, class T4, class T5, class T6>
0205   std::string template_class_name(const char *templateName, unsigned nInclude = 6);
0206   template <class T1, class T2, class T3, class T4, class T5, class T6>
0207   std::string template_class_name(const std::string &templateName, unsigned nInclude = 6);
0208 
0209   // Utility functions for naming stack-based containers such as std::array
0210   template <class T, std::size_t N>
0211   std::string stack_container_name(const char *templateName);
0212 
0213   template <class T, std::size_t N>
0214   std::string stack_container_name(const std::string &templateName);
0215 }  // namespace gs
0216 
0217 #include <cassert>
0218 #include <sstream>
0219 #include <utility>
0220 #include <vector>
0221 
0222 #include "Alignment/Geners/interface/IOIsAnyPtr.hh"
0223 #include "Alignment/Geners/interface/IOIsClassType.hh"
0224 
0225 #ifdef GENERS_EMPTY_TYPE_QUALIFYER_
0226 #undef GENERS_EMPTY_TYPE_QUALIFYER_
0227 #endif
0228 
0229 #define GENERS_EMPTY_TYPE_QUALIFYER_
0230 
0231 // Specializations of "ClassIdSpecialization" for built-in classes.
0232 // They all look the same, so we want to use a macro
0233 #define gs_specialize_class_helper(qualifyer, name, version) /**/                                      \
0234   template <>                                                                                          \
0235   struct ClassIdSpecialization<qualifyer name> {                                                       \
0236     inline static ClassId classId(const bool isPtr = false) { return ClassId(#name, version, isPtr); } \
0237   };
0238 
0239 #define gs_specialize_class_id(name, version) /**/                                                           \
0240   namespace gs {                                                                                             \
0241     gs_specialize_class_helper(GENERS_EMPTY_TYPE_QUALIFYER_, name, version)                                  \
0242         gs_specialize_class_helper(const, name, version) gs_specialize_class_helper(volatile, name, version) \
0243             gs_specialize_class_helper(const volatile, name, version)                                        \
0244   }
0245 
0246 // Specializations of "ClassIdSpecialization" for single-argument templates
0247 #define gs_specialize_template_help_T(qualifyer, name, version, MAX) /**/ \
0248   template <class T>                                                      \
0249   struct ClassIdSpecialization<qualifyer name<T>> {                       \
0250     inline static ClassId classId(const bool isPtr = false) {             \
0251       return ClassId(template_class_name<T>(#name, MAX), version, isPtr); \
0252     }                                                                     \
0253   };
0254 
0255 #define gs_specialize_template_id_T(name, version, MAX) /**/                        \
0256   namespace gs {                                                                    \
0257     gs_specialize_template_help_T(GENERS_EMPTY_TYPE_QUALIFYER_, name, version, MAX) \
0258         gs_specialize_template_help_T(const, name, version, MAX)                    \
0259             gs_specialize_template_help_T(volatile, name, version, MAX)             \
0260                 gs_specialize_template_help_T(const volatile, name, version, MAX)   \
0261   }
0262 
0263 // Specializations of "ClassIdSpecialization" for two-argument templates
0264 #define gs_specialize_template_help_TT(qualifyer, name, version, MAX) /**/   \
0265   template <class T, class U>                                                \
0266   struct ClassIdSpecialization<qualifyer name<T, U>> {                       \
0267     inline static ClassId classId(const bool isPtr = false) {                \
0268       return ClassId(template_class_name<T, U>(#name, MAX), version, isPtr); \
0269     }                                                                        \
0270   };
0271 
0272 #define gs_specialize_template_id_TT(name, version, MAX) /**/                        \
0273   namespace gs {                                                                     \
0274     gs_specialize_template_help_TT(GENERS_EMPTY_TYPE_QUALIFYER_, name, version, MAX) \
0275         gs_specialize_template_help_TT(const, name, version, MAX)                    \
0276             gs_specialize_template_help_TT(volatile, name, version, MAX)             \
0277                 gs_specialize_template_help_TT(const volatile, name, version, MAX)   \
0278   }
0279 
0280 // Specializations of "ClassIdSpecialization" for three-argument templates
0281 #define gs_specialize_template_help_TTT(qualifyer, name, version, MAX) /**/     \
0282   template <class T, class U, class V>                                          \
0283   struct ClassIdSpecialization<qualifyer name<T, U, V>> {                       \
0284     inline static ClassId classId(const bool isPtr = false) {                   \
0285       return ClassId(template_class_name<T, U, V>(#name, MAX), version, isPtr); \
0286     }                                                                           \
0287   };
0288 
0289 #define gs_specialize_template_id_TTT(name, version, MAX) /**/                        \
0290   namespace gs {                                                                      \
0291     gs_specialize_template_help_TTT(GENERS_EMPTY_TYPE_QUALIFYER_, name, version, MAX) \
0292         gs_specialize_template_help_TTT(const, name, version, MAX)                    \
0293             gs_specialize_template_help_TTT(volatile, name, version, MAX)             \
0294                 gs_specialize_template_help_TTT(const volatile, name, version, MAX)   \
0295   }
0296 
0297 // Specializations of "ClassIdSpecialization" for four-argument templates
0298 #define gs_specialize_template_help_TTTT(qualifyer, name, version, MAX) /**/       \
0299   template <class T, class U, class V, class X>                                    \
0300   struct ClassIdSpecialization<qualifyer name<T, U, V, X>> {                       \
0301     inline static ClassId classId(const bool isPtr = false) {                      \
0302       return ClassId(template_class_name<T, U, V, X>(#name, MAX), version, isPtr); \
0303     }                                                                              \
0304   };
0305 
0306 #define gs_specialize_template_id_TTTT(name, version, MAX) /**/                        \
0307   namespace gs {                                                                       \
0308     gs_specialize_template_help_TTTT(GENERS_EMPTY_TYPE_QUALIFYER_, name, version, MAX) \
0309         gs_specialize_template_help_TTTT(const, name, version, MAX)                    \
0310             gs_specialize_template_help_TTTT(volatile, name, version, MAX)             \
0311                 gs_specialize_template_help_TTTT(const volatile, name, version, MAX)   \
0312   }
0313 
0314 // Specializations of "ClassIdSpecialization" for five-argument templates
0315 #define gs_specialize_template_hlp_TTTTT(qualifyer, name, version, MAX) /**/          \
0316   template <class T, class U, class V, class X, class Y>                              \
0317   struct ClassIdSpecialization<qualifyer name<T, U, V, X, Y>> {                       \
0318     inline static ClassId classId(const bool isPtr = false) {                         \
0319       return ClassId(template_class_name<T, U, V, X, Y>(#name, MAX), version, isPtr); \
0320     }                                                                                 \
0321   };
0322 
0323 #define gs_specialize_template_id_TTTTT(name, version, MAX) /**/                       \
0324   namespace gs {                                                                       \
0325     gs_specialize_template_hlp_TTTTT(GENERS_EMPTY_TYPE_QUALIFYER_, name, version, MAX) \
0326         gs_specialize_template_hlp_TTTTT(const, name, version, MAX)                    \
0327             gs_specialize_template_hlp_TTTTT(volatile, name, version, MAX)             \
0328                 gs_specialize_template_hlp_TTTTT(const volatile, name, version, MAX)   \
0329   }
0330 
0331 // Specializations of "ClassIdSpecialization" for six-argument templates
0332 #define gs_specialize_template_h_TTTTTT(qualifyer, name, version, MAX) /**/              \
0333   template <class T, class U, class V, class X, class Y, class Z>                        \
0334   struct ClassIdSpecialization<qualifyer name<T, U, V, X, Y, Z>> {                       \
0335     inline static ClassId classId(const bool isPtr = false) {                            \
0336       return ClassId(template_class_name<T, U, V, X, Y, Z>(#name, MAX), version, isPtr); \
0337     }                                                                                    \
0338   };
0339 
0340 #define gs_specialize_template_id_TTTTTT(name, version, MAX) /**/                     \
0341   namespace gs {                                                                      \
0342     gs_specialize_template_h_TTTTTT(GENERS_EMPTY_TYPE_QUALIFYER_, name, version, MAX) \
0343         gs_specialize_template_h_TTTTTT(const, name, version, MAX)                    \
0344             gs_specialize_template_h_TTTTTT(volatile, name, version, MAX)             \
0345                 gs_specialize_template_h_TTTTTT(const volatile, name, version, MAX)   \
0346   }
0347 
0348 // Specializations of "ClassIdSpecialization" for two-argument templates
0349 // which include an integer as a second argument (like std::array)
0350 #define gs_specialize_template_help_TN(qualifyer, name, version, MAX) /**/    \
0351   template <class T, std::size_t N>                                           \
0352   struct ClassIdSpecialization<qualifyer name<T, N>> {                        \
0353     inline static ClassId classId(const bool isPtr = false) {                 \
0354       return ClassId(stack_container_name<T, N>(#name, MAX), version, isPtr); \
0355     }                                                                         \
0356   };
0357 
0358 #define gs_specialize_template_id_TN(name, version, MAX) /**/                        \
0359   namespace gs {                                                                     \
0360     gs_specialize_template_help_TN(GENERS_EMPTY_TYPE_QUALIFYER_, name, version, MAX) \
0361         gs_specialize_template_help_TN(const, name, version, MAX)                    \
0362             gs_specialize_template_help_TN(volatile, name, version, MAX)             \
0363                 gs_specialize_template_help_TN(const volatile, name, version, MAX)   \
0364   }
0365 
0366 namespace gs {
0367   // "template_class_name" implementations
0368   template <class T>
0369   std::string template_class_name(const char *templateName, const unsigned nInclude) {
0370     assert(templateName);
0371     std::string name(templateName);
0372     if (nInclude) {
0373       name += '<';
0374       const ClassId &id(ClassIdSpecialization<T>::classId());
0375       name += id.id();
0376       name += '>';
0377     }
0378     return name;
0379   }
0380 
0381   template <class T>
0382   inline std::string template_class_name(const std::string &templateName, const unsigned nInclude) {
0383     return template_class_name<T>(templateName.c_str(), nInclude);
0384   }
0385 
0386   template <class T1, class T2>
0387   std::string template_class_name(const char *templateName, const unsigned nInclude) {
0388     assert(templateName);
0389     std::string name(templateName);
0390     if (nInclude) {
0391       name += '<';
0392       const ClassId &id1(ClassIdSpecialization<T1>::classId());
0393       name += id1.id();
0394       if (nInclude > 1) {
0395         name += ',';
0396         const ClassId &id2(ClassIdSpecialization<T2>::classId());
0397         name += id2.id();
0398       }
0399       name += '>';
0400     }
0401     return name;
0402   }
0403 
0404   template <class T1, class T2>
0405   inline std::string template_class_name(const std::string &templateName, const unsigned nInclude) {
0406     return template_class_name<T1, T2>(templateName.c_str(), nInclude);
0407   }
0408 
0409   template <class T1, class T2, class T3>
0410   std::string template_class_name(const char *templateName, const unsigned nInclude) {
0411     assert(templateName);
0412     std::string name(templateName);
0413     if (nInclude) {
0414       name += '<';
0415       const ClassId &id1(ClassIdSpecialization<T1>::classId());
0416       name += id1.id();
0417       if (nInclude > 1) {
0418         name += ',';
0419         const ClassId &id2(ClassIdSpecialization<T2>::classId());
0420         name += id2.id();
0421       }
0422       if (nInclude > 2) {
0423         name += ',';
0424         const ClassId &id3(ClassIdSpecialization<T3>::classId());
0425         name += id3.id();
0426       }
0427       name += '>';
0428     }
0429     return name;
0430   }
0431 
0432   template <class T1, class T2, class T3>
0433   inline std::string template_class_name(const std::string &templateName, const unsigned nInclude) {
0434     return template_class_name<T1, T2, T3>(templateName.c_str(), nInclude);
0435   }
0436 
0437   template <class T1, class T2, class T3, class T4>
0438   std::string template_class_name(const char *templateName, const unsigned nInclude) {
0439     assert(templateName);
0440     std::string name(templateName);
0441     if (nInclude) {
0442       name += '<';
0443       const ClassId &id1(ClassIdSpecialization<T1>::classId());
0444       name += id1.id();
0445       if (nInclude > 1) {
0446         name += ',';
0447         const ClassId &id2(ClassIdSpecialization<T2>::classId());
0448         name += id2.id();
0449       }
0450       if (nInclude > 2) {
0451         name += ',';
0452         const ClassId &id3(ClassIdSpecialization<T3>::classId());
0453         name += id3.id();
0454       }
0455       if (nInclude > 3) {
0456         name += ',';
0457         const ClassId &id4(ClassIdSpecialization<T4>::classId());
0458         name += id4.id();
0459       }
0460       name += '>';
0461     }
0462     return name;
0463   }
0464 
0465   template <class T1, class T2, class T3, class T4>
0466   inline std::string template_class_name(const std::string &templateName, const unsigned n) {
0467     return template_class_name<T1, T2, T3, T4>(templateName.c_str(), n);
0468   }
0469 
0470   template <class T1, class T2, class T3, class T4, class T5>
0471   std::string template_class_name(const char *templateName, const unsigned nInclude) {
0472     assert(templateName);
0473     std::string name(templateName);
0474     if (nInclude) {
0475       name += '<';
0476       const ClassId &id1(ClassIdSpecialization<T1>::classId());
0477       name += id1.id();
0478       if (nInclude > 1) {
0479         name += ',';
0480         const ClassId &id2(ClassIdSpecialization<T2>::classId());
0481         name += id2.id();
0482       }
0483       if (nInclude > 2) {
0484         name += ',';
0485         const ClassId &id3(ClassIdSpecialization<T3>::classId());
0486         name += id3.id();
0487       }
0488       if (nInclude > 3) {
0489         name += ',';
0490         const ClassId &id4(ClassIdSpecialization<T4>::classId());
0491         name += id4.id();
0492       }
0493       if (nInclude > 4) {
0494         name += ',';
0495         const ClassId &id5(ClassIdSpecialization<T5>::classId());
0496         name += id5.id();
0497       }
0498       name += '>';
0499     }
0500     return name;
0501   }
0502 
0503   template <class T1, class T2, class T3, class T4, class T5>
0504   inline std::string template_class_name(const std::string &templateName, const unsigned n) {
0505     return template_class_name<T1, T2, T3, T4, T5>(templateName.c_str(), n);
0506   }
0507 
0508   template <class T1, class T2, class T3, class T4, class T5, class T6>
0509   std::string template_class_name(const char *templateName, const unsigned nInclude) {
0510     assert(templateName);
0511     std::string name(templateName);
0512     if (nInclude) {
0513       name += '<';
0514       const ClassId &id1(ClassIdSpecialization<T1>::classId());
0515       name += id1.id();
0516       if (nInclude > 1) {
0517         name += ',';
0518         const ClassId &id2(ClassIdSpecialization<T2>::classId());
0519         name += id2.id();
0520       }
0521       if (nInclude > 2) {
0522         name += ',';
0523         const ClassId &id3(ClassIdSpecialization<T3>::classId());
0524         name += id3.id();
0525       }
0526       if (nInclude > 3) {
0527         name += ',';
0528         const ClassId &id4(ClassIdSpecialization<T4>::classId());
0529         name += id4.id();
0530       }
0531       if (nInclude > 4) {
0532         name += ',';
0533         const ClassId &id5(ClassIdSpecialization<T5>::classId());
0534         name += id5.id();
0535       }
0536       if (nInclude > 5) {
0537         name += ',';
0538         const ClassId &id6(ClassIdSpecialization<T6>::classId());
0539         name += id6.id();
0540       }
0541       name += '>';
0542     }
0543     return name;
0544   }
0545 
0546   template <class T1, class T2, class T3, class T4, class T5, class T6>
0547   inline std::string template_class_name(const std::string &templateName, const unsigned n) {
0548     return template_class_name<T1, T2, T3, T4, T5, T6>(templateName.c_str(), n);
0549   }
0550 
0551   template <class T, std::size_t N>
0552   std::string stack_container_name(const char *templateName) {
0553     assert(templateName);
0554     const ClassId &id1(ClassIdSpecialization<T>::classId());
0555     std::ostringstream os;
0556     os << templateName << '<' << id1.id() << ',' << N << "(0)>";
0557     return os.str();
0558   }
0559 
0560   template <class T, std::size_t N>
0561   std::string stack_container_name(const std::string &templateName) {
0562     return stack_container_name<T, N>(templateName.c_str());
0563   }
0564 
0565   // Skip references in class ids
0566   template <class T>
0567   struct ClassIdSpecialization<T &> {
0568     inline static ClassId classId(const bool isPtr = false) { return ClassIdSpecialization<T>::classId(isPtr); }
0569   };
0570 
0571   // Skip pointers in class ids
0572   template <class T>
0573   struct ClassIdSpecialization<T *> {
0574     inline static ClassId classId(const bool /* isPtr */ = false) { return ClassIdSpecialization<T>::classId(true); }
0575   };
0576 
0577   template <class T>
0578   struct ClassIdSpecialization<T *const> {
0579     inline static ClassId classId(const bool /* isPtr */ = false) { return ClassIdSpecialization<T>::classId(true); }
0580   };
0581 
0582   template <class T>
0583   struct ClassIdSpecialization<T *volatile> {
0584     inline static ClassId classId(const bool /* isPtr */ = false) { return ClassIdSpecialization<T>::classId(true); }
0585   };
0586 
0587   template <class T>
0588   struct ClassIdSpecialization<T *const volatile> {
0589     inline static ClassId classId(const bool /* isPtr */ = false) { return ClassIdSpecialization<T>::classId(true); }
0590   };
0591 
0592   // Skip shared pointers in class ids
0593   template <class T>
0594   struct ClassIdSpecialization<std::shared_ptr<T>> {
0595     inline static ClassId classId(const bool /* isPtr */ = false) { return ClassIdSpecialization<T>::classId(true); }
0596   };
0597 
0598   template <class T>
0599   struct ClassIdSpecialization<const std::shared_ptr<T>> {
0600     inline static ClassId classId(const bool /* isPtr */ = false) { return ClassIdSpecialization<T>::classId(true); }
0601   };
0602 
0603   template <class T>
0604   struct ClassIdSpecialization<volatile std::shared_ptr<T>> {
0605     inline static ClassId classId(const bool /* isPtr */ = false) { return ClassIdSpecialization<T>::classId(true); }
0606   };
0607 
0608   template <class T>
0609   struct ClassIdSpecialization<const volatile std::shared_ptr<T>> {
0610     inline static ClassId classId(const bool /* isPtr */ = false) { return ClassIdSpecialization<T>::classId(true); }
0611   };
0612 
0613   // Skip IOPtr in class ids and do not turn on the pointer flag
0614   template <class T>
0615   struct ClassIdSpecialization<IOPtr<T>> {
0616     inline static ClassId classId(const bool isPtr = false) { return ClassIdSpecialization<T>::classId(isPtr); }
0617   };
0618 
0619   template <class T>
0620   struct ClassIdSpecialization<const IOPtr<T>> {
0621     inline static ClassId classId(const bool isPtr = false) { return ClassIdSpecialization<T>::classId(isPtr); }
0622   };
0623 
0624   template <class T>
0625   struct ClassIdSpecialization<volatile IOPtr<T>> {
0626     inline static ClassId classId(const bool isPtr = false) { return ClassIdSpecialization<T>::classId(isPtr); }
0627   };
0628 
0629   template <class T>
0630   struct ClassIdSpecialization<const volatile IOPtr<T>> {
0631     inline static ClassId classId(const bool isPtr = false) { return ClassIdSpecialization<T>::classId(isPtr); }
0632   };
0633 
0634   // Same thing for IOProxy
0635   template <class T>
0636   struct ClassIdSpecialization<IOProxy<T>> {
0637     inline static ClassId classId(const bool isPtr = false) { return ClassIdSpecialization<T>::classId(isPtr); }
0638   };
0639 
0640   template <class T>
0641   struct ClassIdSpecialization<const IOProxy<T>> {
0642     inline static ClassId classId(const bool isPtr = false) { return ClassIdSpecialization<T>::classId(isPtr); }
0643   };
0644 
0645   template <class T>
0646   struct ClassIdSpecialization<volatile IOProxy<T>> {
0647     inline static ClassId classId(const bool isPtr = false) { return ClassIdSpecialization<T>::classId(isPtr); }
0648   };
0649 
0650   template <class T>
0651   struct ClassIdSpecialization<const volatile IOProxy<T>> {
0652     inline static ClassId classId(const bool isPtr = false) { return ClassIdSpecialization<T>::classId(isPtr); }
0653   };
0654 
0655   // The remaining ClassId static functions
0656   template <class T>
0657   inline ClassId ClassId::makeId() {
0658     return ClassIdSpecialization<T>::classId();
0659   }
0660 
0661   namespace Private {
0662     template <bool, class T>
0663     struct CallClassId {
0664       static inline ClassId get(const T &) { return ClassIdSpecialization<T>::classId(); }
0665     };
0666 
0667     template <class T>
0668     struct CallClassId<true, T> {
0669       static inline ClassId get(const T &obj) { return obj.classId(); }
0670     };
0671 
0672     // The following class will check for the existence of two
0673     // possible signatures of the "classId" method:
0674     // "const ClassId& classId() const" and "ClassId classId() const".
0675     template <class Tp>
0676     class TypeHasClassIdHelper {
0677       template <typename T, T>
0678       struct TypeCheck;
0679       template <typename T>
0680       struct FcnType1 {
0681         typedef ClassId (T::*fptr)() const;
0682       };
0683       template <typename T>
0684       struct FcnType2 {
0685         typedef const ClassId &(T::*fptr)() const;
0686       };
0687 
0688       typedef char Yes;
0689       typedef struct {
0690         char a[2];
0691       } No;
0692 
0693       template <typename T>
0694       static Yes Has1(TypeCheck<typename FcnType1<T>::fptr, &T::classId> *);
0695       template <typename T>
0696       static No Has1(...);
0697 
0698       template <typename T>
0699       static Yes Has2(TypeCheck<typename FcnType2<T>::fptr, &T::classId> *);
0700       template <typename T>
0701       static No Has2(...);
0702 
0703     public:
0704       static const bool value = ((sizeof(Has1<Tp>(0)) == sizeof(Yes)) || (sizeof(Has2<Tp>(0)) == sizeof(Yes)));
0705     };
0706 
0707     template <class T, bool b = IOIsClassType<T>::value>
0708     struct TypeHasClassId {
0709       static const bool value = false;
0710     };
0711 
0712     template <typename T>
0713     struct TypeHasClassId<T, true> {
0714       static const bool value = TypeHasClassIdHelper<T>::value;
0715     };
0716   }  // namespace Private
0717 
0718   template <class T>
0719   inline ClassId ClassId::itemId(const T &item) {
0720     // Make sure that item is not a pointer.
0721     static_assert((!IOIsAnyPtr<T>::value), "can not use pointers with this method");
0722 
0723     // If the classId() function is avalable for this item, call it
0724     // (it could be virtual). Otherwise, call the generic method.
0725     return Private::CallClassId<Private::TypeHasClassId<T>::value, T>::get(item);
0726   }
0727 }  // namespace gs
0728 
0729 // Class ids for standard types
0730 gs_specialize_class_id(float, 0) gs_specialize_class_id(double, 0) gs_specialize_class_id(long double, 0)
0731     gs_specialize_class_id(int, 0) gs_specialize_class_id(unsigned, 0) gs_specialize_class_id(long, 0)
0732         gs_specialize_class_id(long long, 0) gs_specialize_class_id(unsigned long, 0)
0733             gs_specialize_class_id(unsigned long long, 0) gs_specialize_class_id(short, 0)
0734                 gs_specialize_class_id(unsigned short, 0) gs_specialize_class_id(bool, 0)
0735                     gs_specialize_class_id(char, 0) gs_specialize_class_id(unsigned char, 0)
0736                         gs_specialize_class_id(signed char, 0) gs_specialize_class_id(void, 0)
0737                             gs_specialize_class_id(std::string, 0)
0738 
0739     // Class ids for some standard library templates
0740     // used by this I/O package
0741     gs_specialize_template_id_T(std::less, 0, 1) gs_specialize_template_id_T(std::equal_to, 0, 1)
0742         gs_specialize_template_id_T(std::allocator, 0, 1) gs_specialize_template_id_T(std::char_traits, 0, 1)
0743             gs_specialize_template_id_TT(std::vector, 0, 1) gs_specialize_template_id_TT(std::pair, 0, 2)
0744                 gs_specialize_template_id_TTT(std::basic_string, 0, 2)
0745 
0746 #endif  // GENERS_CLASSID_HH_