1 // @(#)root/meta:$Id$ 2 // Author: Rene Brun 07/01/95 3 4 /************************************************************************* 5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * 6 * All rights reserved. * 7 * * 8 * For the licensing terms see $ROOTSYS/LICENSE. * 9 * For the list of contributors see $ROOTSYS/README/CREDITS. * 10 *************************************************************************/ 11 12 #ifndef ROOT_TClass 13 #define ROOT_TClass 14 15 16 ////////////////////////////////////////////////////////////////////////// 17 // // 18 // TClass // 19 // // 20 // Dictionary of a class. // 21 // // 22 ////////////////////////////////////////////////////////////////////////// 23 24 #ifndef ROOT_TDictionary 25 #include "TDictionary.h" 26 #endif 27 #ifndef ROOT_TString 28 #include "TString.h" 29 #endif 30 #ifndef ROOT_TObjArray 31 #include "TObjArray.h" 32 #endif 33 #ifndef ROOT_TObjString 34 #include "TObjString.h" 35 #endif 36 #include <map> 37 #include <string> 38 #if __cplusplus >= 201103L 39 #include <atomic> 40 #endif 41 #ifndef ROOT_ThreadLocalStorage 42 #include "ThreadLocalStorage.h" 43 #endif 44 class TBaseClass; 45 class TBrowser; 46 class TDataMember; 47 class TMethod; 48 class TRealData; 49 class TCint; 50 class TBuffer; 51 class TVirtualStreamerInfo; 52 class TVirtualCollectionProxy; 53 class TMethodCall; 54 class TVirtualIsAProxy; 55 class TVirtualRefProxy; 56 class THashTable; 57 58 namespace clang { 59 class Decl; 60 } 61 62 namespace ROOT { 63 class TGenericClassInfo; 64 class TCollectionProxyInfo; 65 class TSchemaRuleSet; 66 } 67 68 namespace ROOT { 69 class TMapTypeToTClass; 70 } 71 typedef ROOT::TMapTypeToTClass IdMap_t; 72 73 class TClass : public TDictionary { 74 75 friend class TCint; 76 friend class TCintWithCling; 77 friend void ROOT::ResetClassVersion(TClass*, const char*, Short_t); 78 friend class ROOT::TGenericClassInfo; 79 80 public: 81 // TClass status bits 82 enum { kClassSaved = BIT(12), kIgnoreTObjectStreamer = BIT(15), 83 kUnloaded = BIT(16), kIsTObject = BIT(17), 84 kIsForeign = BIT(18), kIsEmulation = BIT(19), 85 kStartWithTObject = BIT(20), // see comments for IsStartingWithTObject() 86 kWarned = BIT(21), 87 kHasNameMapNode = BIT(22) 88 }; 89 enum ENewType { kRealNew = 0, kClassNew, kDummyNew }; 90 enum ECheckSum { 91 kCurrentCheckSum = 0, 92 kNoEnum = 1, // Used since v3.3 93 kNoRange = 2, // Up to v5.17 94 kWithTypeDef = 3, // Up to v5.34.18 and v5.99/06 95 kNoBaseCheckSum = 4, // Up to v5.34.18 and v5.99/06 96 kLatestCheckSum = 5 97 }; 98 99 private: 100 101 // TClass objects can be created as a result of opening a TFile (in which 102 // they are in emulated mode) or as a result of loading the dictionary for 103 // the corresponding class. When a dictionary is loaded any pre-existing 104 // emulated TClass is replaced by the one created/coming from the dictionary. 105 // To have a reference that always point to the 'current' TClass object for 106 // a given class, one should use a TClassRef. 107 // TClassRef works by holding on to the fPersistentRef which is updated 108 // atomically whenever a TClass is replaced. During the replacement the 109 // value of fPersistentRef is set to zero, leading the TClassRef to call 110 // TClass::GetClass which is also locked by the replacement. At the end 111 // of the replacement, fPersistentRef points to the new TClass object. 112 #if __cplusplus >= 201103L 113 std::atomic<TClass**> fPersistentRef;//!Persistent address of pointer to this TClass object and its successors. 114 #else 115 TClass **fPersistentRef; //!Persistent address of pointer to this TClass object and its successors. 116 #endif 117 118 119 mutable TObjArray *fStreamerInfo; //Array of TVirtualStreamerInfo 120 #if __cplusplus >= 201103L 121 mutable std::atomic<std::map<std::string, TObjArray*>*> fConversionStreamerInfo; //Array of the streamer infos derived from another class. 122 #else 123 mutable std::map<std::string, TObjArray*> *fConversionStreamerInfo; //Array of the streamer infos derived from another class. 124 #endif 125 TList *fRealData; //linked list for persistent members including base classes 126 TList *fBase; //linked list for base classes 127 TList *fData; //linked list for data members 128 TList *fMethod; //linked list for methods 129 TList *fAllPubData; //all public data members (including from base classes) 130 TList *fAllPubMethod; //all public methods (including from base classes) 131 mutable TList *fClassMenuList; //list of class menu items 132 133 const char *fDeclFileName; //name of class declaration file 134 const char *fImplFileName; //name of class implementation file 135 Short_t fDeclFileLine; //line of class declaration 136 Short_t fImplFileLine; //line of class implementation 137 UInt_t fInstanceCount; //number of instances of this class 138 UInt_t fOnHeap; //number of instances on heap 139 mutable UInt_t fCheckSum; //checksum of data members and base classes 140 TVirtualCollectionProxy *fCollectionProxy; //Collection interface 141 Version_t fClassVersion; //Class version Identifier 142 ClassInfo_t *fClassInfo; //pointer to CINT class info class 143 TString fContextMenuTitle;//context menu title 144 const type_info *fTypeInfo; //pointer to the C++ type information. 145 ShowMembersFunc_t fShowMembers; //pointer to the class's ShowMembers function 146 #if __cplusplus >= 201103L 147 mutable std::atomic<void*> fInterShowMembers;//Interpreter call setup for ShowMembers 148 #else 149 mutable void *fInterShowMembers;//Interpreter call setup for ShowMembers 150 #endif 151 TClassStreamer *fStreamer; //pointer to streamer function 152 TString fSharedLibs; //shared libraries containing class code 153 154 TVirtualIsAProxy *fIsA; //!pointer to the class's IsA proxy. 155 IsAGlobalFunc_t fGlobalIsA; //pointer to a global IsA function. 156 #if __cplusplus >= 201103L 157 mutable std::atomic<TMethodCall*> fIsAMethod; //!saved info to call a IsA member function 158 #else 159 mutable TMethodCall *fIsAMethod; //!saved info to call a IsA member function 160 #endif 161 162 ROOT::MergeFunc_t fMerge; //pointer to a function implementing Merging objects of this class. 163 ROOT::ResetAfterMergeFunc_t fResetAfterMerge; //pointer to a function implementing Merging objects of this class. 164 ROOT::NewFunc_t fNew; //pointer to a function newing one object. 165 ROOT::NewArrFunc_t fNewArray; //pointer to a function newing an array of objects. 166 ROOT::DelFunc_t fDelete; //pointer to a function deleting one object. 167 ROOT::DelArrFunc_t fDeleteArray; //pointer to a function deleting an array of objects. 168 ROOT::DesFunc_t fDestructor; //pointer to a function call an object's destructor. 169 ROOT::DirAutoAdd_t fDirAutoAdd; //pointer which implements the Directory Auto Add feature for this class.']' 170 ClassStreamerFunc_t fStreamerFunc; //Wrapper around this class custom Streamer member function. 171 Int_t fSizeof; //Sizeof the class. 172 173 mutable Int_t fCanSplit; //!Indicates whether this class can be split or not. 174 #if __cplusplus >= 201103L 175 mutable std::atomic<Long_t> fProperty; //!Property 176 mutable std::atomic<Bool_t> fVersionUsed; //!Indicates whether GetClassVersion has been called 177 #else 178 mutable Long_t fProperty; //!Property 179 mutable Bool_t fVersionUsed; //!Indicates whether GetClassVersion has been called 180 #endif 181 182 mutable Bool_t fIsOffsetStreamerSet; //!saved remember if fOffsetStreamer has been set. 183 mutable Long_t fOffsetStreamer; //!saved info to call Streamer 184 Int_t fStreamerType; //!cached of the streaming method to use 185 #if __cplusplus >= 201103L 186 mutable std::atomic<TVirtualStreamerInfo*> fCurrentInfo; //!cached current streamer info. 187 mutable std::atomic<TVirtualStreamerInfo*> fLastReadInfo; //!cached streamer info used in the last read. 188 #else 189 mutable TVirtualStreamerInfo *fCurrentInfo; //!cached current streamer info. 190 mutable TVirtualStreamerInfo *fLastReadInfo; //!cached streamer info used in the last read. 191 #endif 192 TVirtualRefProxy *fRefProxy; //!Pointer to reference proxy if this class represents a reference 193 ROOT::TSchemaRuleSet *fSchemaRules; //! Schema evolution rules 194 195 typedef void (TClass::*StreamerImpl_t)(void *obj, TBuffer &b, const TClass *onfile_class) const; 196 mutable StreamerImpl_t fStreamerImpl;//! Pointer to the function implementing the right streaming behavior for the class represented by this object. 197 198 TMethod *GetClassMethod(Long_t faddr); 199 TMethod *GetClassMethod(const char *name, const char *signature); 200 Int_t GetBaseClassOffsetRecurse(const TClass *base); 201 void Init(const char *name, Version_t cversion, const type_info *info, 202 TVirtualIsAProxy *isa, ShowMembersFunc_t showmember, 203 const char *dfil, const char *ifil, 204 Int_t dl, Int_t il, 205 Bool_t silent); 206 void ForceReload (TClass* oldcl); 207 208 void SetClassVersion(Version_t version); 209 void SetClassSize(Int_t sizof) { fSizeof = sizof; } 210 TVirtualStreamerInfo* DetermineCurrentStreamerInfo(); 211 212 // Various implementation for TClass::Stramer 213 void StreamerExternal(void *object, TBuffer &b, const TClass *onfile_class) const; 214 void StreamerTObject(void *object, TBuffer &b, const TClass *onfile_class) const; 215 void StreamerTObjectInitialized(void *object, TBuffer &b, const TClass *onfile_class) const; 216 void StreamerTObjectEmulated(void *object, TBuffer &b, const TClass *onfile_class) const; 217 void StreamerInstrumented(void *object, TBuffer &b, const TClass *onfile_class) const; 218 void StreamerStreamerInfo(void *object, TBuffer &b, const TClass *onfile_class) const; 219 void StreamerDefault(void *object, TBuffer &b, const TClass *onfile_class) const; 220 221 static IdMap_t *GetIdMap(); //Map from typeid to TClass pointer 222 #if __cplusplus >= 201103L 223 static std::atomic<Int_t> fgClassCount; //provides unique id for a each class 224 //stored in TObject::fUniqueID 225 #else 226 static Int_t fgClassCount; //provides unique id for a each class 227 //stored in TObject::fUniqueID 228 #endif 229 // Internal status bits 230 enum { kLoading = BIT(14) }; 231 // Internal streamer type. 232 enum EStreamerType {kDefault=0, kEmulated=1, kTObject=2, kInstrumented=4, kForeign=8, kExternal=16}; 233 234 // When a new class is created, we need to be able to find 235 // if there are any existing classes that have the same name 236 // after any typedefs are expanded. (This only really affects 237 // template arguments.) To avoid having to search through all classes 238 // in that case, we keep a hash table mapping from the fully 239 // typedef-expanded names to the original class names. 240 // An entry is made in the table only if they are actually different. 241 // 242 // In these objects, the TObjString base holds the typedef-expanded 243 // name (the hash key), and fOrigName holds the original class name 244 // (the value to which the key maps). 245 // 246 class TNameMapNode : public TObjString 247 { 248 public: 249 TNameMapNode (const char* typedf, const char* orig); 250 TString fOrigName; 251 }; 252 253 // These are the above-referenced hash tables. (The pointers are null 254 // if no entries have been made.) There are actually two variants. 255 // In the first, the typedef names are resolved with 256 // TClassEdit::ResolveTypedef; in the second, the class names 257 // are first massaged with TClassEdit::ShortType with kDropStlDefault. 258 // (??? Are the two distinct tables really needed?) 259 static THashTable* fgClassTypedefHash; 260 static THashTable* fgClassShortTypedefHash; 261 262 private: 263 TClass(const TClass& tc); 264 TClass& operator=(const TClass&); 265 266 protected: 267 TVirtualStreamerInfo *FindStreamerInfo(TObjArray* arr, UInt_t checksum) const; 268 static THashTable *GetClassShortTypedefHash(); 269 270 public: 271 TClass(); 272 TClass(const char *name, Bool_t silent = kFALSE); 273 TClass(const char *name, Version_t cversion, 274 const char *dfil = 0, const char *ifil = 0, 275 Int_t dl = 0, Int_t il = 0, Bool_t silent = kFALSE); 276 TClass(const char *name, Version_t cversion, 277 const type_info &info, TVirtualIsAProxy *isa, 278 ShowMembersFunc_t showmember, 279 const char *dfil, const char *ifil, 280 Int_t dl, Int_t il, Bool_t silent = kFALSE); 281 virtual ~TClass(); 282 283 void AddInstance(Bool_t heap = kFALSE) { fInstanceCount++; if (heap) fOnHeap++; } 284 void AddImplFile(const char *filename, int line); 285 static Bool_t AddRule(const char *rule); 286 static Int_t ReadRules(const char *filename); 287 static Int_t ReadRules(); 288 void AdoptSchemaRules( ROOT::TSchemaRuleSet *rules ); 289 virtual void Browse(TBrowser *b); 290 void BuildRealData(void *pointer=0, Bool_t isTransient = kFALSE); 291 void BuildEmulatedRealData(const char *name, Long_t offset, TClass *cl); 292 void CalculateStreamerOffset() const; 293 Bool_t CallShowMembers(void* obj, TMemberInspector &insp, 294 Int_t isATObject = -1) const; 295 Bool_t CanSplit() const; 296 Bool_t CanIgnoreTObjectStreamer() { return TestBit(kIgnoreTObjectStreamer);} 297 TObject *Clone(const char *newname="") const; 298 void CopyCollectionProxy(const TVirtualCollectionProxy&); 299 void Draw(Option_t *option=""); 300 void Dump() const { TDictionary::Dump(); } 301 void Dump(void *obj) const; 302 char *EscapeChars(const char *text) const; 303 TVirtualStreamerInfo *FindStreamerInfo(UInt_t checksum) const; 304 TVirtualStreamerInfo *GetConversionStreamerInfo( const char* onfile_classname, Int_t version ) const; 305 TVirtualStreamerInfo *FindConversionStreamerInfo( const char* onfile_classname, UInt_t checksum ) const; 306 TVirtualStreamerInfo *GetConversionStreamerInfo( const TClass* onfile_cl, Int_t version ) const; 307 TVirtualStreamerInfo *FindConversionStreamerInfo( const TClass* onfile_cl, UInt_t checksum ) const; 308 Bool_t HasDefaultConstructor() const; 309 UInt_t GetCheckSum(ECheckSum code = kCurrentCheckSum) const; 310 TVirtualCollectionProxy *GetCollectionProxy() const; 311 TVirtualIsAProxy *GetIsAProxy() const; 312 Version_t GetClassVersion() const { fVersionUsed = kTRUE; return fClassVersion; } 313 Int_t GetClassSize() const { return Size(); } 314 TDataMember *GetDataMember(const char *datamember) const; 315 Long_t GetDataMemberOffset(const char *membername) const; 316 const char *GetDeclFileName() const { return fDeclFileName; } 317 Short_t GetDeclFileLine() const { return fDeclFileLine; } 318 ROOT::DelFunc_t GetDelete() const; 319 ROOT::DesFunc_t GetDestructor() const; 320 ROOT::DelArrFunc_t GetDeleteArray() const; 321 ClassInfo_t *GetClassInfo() const { return fClassInfo; } 322 const char *GetContextMenuTitle() const { return fContextMenuTitle; } 323 TVirtualStreamerInfo *GetCurrentStreamerInfo() { 324 if (fCurrentInfo) return fCurrentInfo; 325 else return DetermineCurrentStreamerInfo(); 326 } 327 TVirtualStreamerInfo *GetLastReadInfo() const { return fLastReadInfo; } 328 void SetLastReadInfo(TVirtualStreamerInfo *info) { fLastReadInfo = info; } 329 TList *GetListOfDataMembers(); 330 TList *GetListOfBases(); 331 TList *GetListOfMethods(); 332 TList *GetListOfRealData() const { return fRealData; } 333 TList *GetListOfAllPublicMethods(); 334 TList *GetListOfAllPublicDataMembers(); 335 const char *GetImplFileName() const { return fImplFileName; } 336 Short_t GetImplFileLine() const { return fImplFileLine; } 337 TClass *GetActualClass(const void *object) const; 338 TClass *GetBaseClass(const char *classname); 339 TClass *GetBaseClass(const TClass *base); 340 Int_t GetBaseClassOffset(const TClass *base); 341 TClass *GetBaseDataMember(const char *datamember); 342 ROOT::DirAutoAdd_t GetDirectoryAutoAdd() const; 343 UInt_t GetInstanceCount() const { return fInstanceCount; } 344 UInt_t GetHeapInstanceCount() const { return fOnHeap; } 345 void GetMenuItems(TList *listitems); 346 TList *GetMenuList() const; 347 TMethod *GetMethod(const char *method, const char *params); 348 TMethod *GetMethodWithPrototype(const char *method, const char *proto); 349 TMethod *GetMethodAny(const char *method); 350 TMethod *GetMethodAllAny(const char *method); 351 Int_t GetNdata(); 352 ROOT::MergeFunc_t GetMerge() const; 353 ROOT::ResetAfterMergeFunc_t GetResetAfterMerge() const; 354 ROOT::NewFunc_t GetNew() const; 355 ROOT::NewArrFunc_t GetNewArray() const; 356 Int_t GetNmethods(); 357 #ifdef __CINT__ 358 TClass **GetPersistentRef() const { return fPersistentRef; } 359 #else 360 TClass *const*GetPersistentRef() const { return fPersistentRef; } 361 #endif 362 TRealData *GetRealData(const char *name) const; 363 TVirtualRefProxy *GetReferenceProxy() const { return fRefProxy; } 364 const ROOT::TSchemaRuleSet *GetSchemaRules() const; 365 ROOT::TSchemaRuleSet *GetSchemaRules(Bool_t create = kFALSE); 366 const char *GetSharedLibs(); 367 ShowMembersFunc_t GetShowMembersWrapper() const { return fShowMembers; } 368 TClassStreamer *GetStreamer() const; 369 ClassStreamerFunc_t GetStreamerFunc() const; 370 TObjArray *GetStreamerInfos() const { return fStreamerInfo; } 371 TVirtualStreamerInfo *GetStreamerInfo(Int_t version=0) const; 372 TVirtualStreamerInfo *GetStreamerInfoAbstractEmulated(Int_t version=0) const; 373 TVirtualStreamerInfo *FindStreamerInfoAbstractEmulated(UInt_t checksum) const; 374 const type_info *GetTypeInfo() const { return fTypeInfo; }; 375 void IgnoreTObjectStreamer(Bool_t ignore=kTRUE); 376 Bool_t InheritsFrom(const char *cl) const; 377 Bool_t InheritsFrom(const TClass *cl) const; 378 void InterpretedShowMembers(void* obj, TMemberInspector &insp); 379 Bool_t IsFolder() const { return kTRUE; } 380 Bool_t IsLoaded() const; 381 Bool_t IsForeign() const; 382 Bool_t IsStartingWithTObject() const; 383 Bool_t IsVersioned() const { return !( GetClassVersion()<=1 && IsForeign() ); } 384 Bool_t IsTObject() const; 385 void ls(Option_t *opt="") const; 386 void MakeCustomMenuList(); 387 Bool_t MatchLegacyCheckSum(UInt_t checksum) const; 388 void Move(void *arenaFrom, void *arenaTo) const; 389 void *New(ENewType defConstructor = kClassNew) const; 390 void *New(void *arena, ENewType defConstructor = kClassNew) const; 391 void *NewArray(Long_t nElements, ENewType defConstructor = kClassNew) const; 392 void *NewArray(Long_t nElements, void *arena, ENewType defConstructor = kClassNew) const; 393 virtual void PostLoadCheck(); 394 Long_t Property() const; 395 Int_t ReadBuffer(TBuffer &b, void *pointer, Int_t version, UInt_t start, UInt_t count); 396 Int_t ReadBuffer(TBuffer &b, void *pointer); 397 void ReplaceWith(TClass *newcl, Bool_t recurse = kTRUE) const; 398 void ResetClassInfo(Long_t tagnum); 399 void ResetInstanceCount() { fInstanceCount = fOnHeap = 0; } 400 void ResetMenuList(); 401 Int_t Size() const; 402 void SetCanSplit(Int_t splitmode); 403 void SetCollectionProxy(const ROOT::TCollectionProxyInfo&); 404 void SetContextMenuTitle(const char *title); 405 void SetCurrentStreamerInfo(TVirtualStreamerInfo *info); 406 void SetGlobalIsA(IsAGlobalFunc_t); 407 void SetDeclFile(const char *name, int line) { fDeclFileName = name; fDeclFileLine = line; } 408 void SetDelete(ROOT::DelFunc_t deleteFunc); 409 void SetDeleteArray(ROOT::DelArrFunc_t deleteArrayFunc); 410 void SetDirectoryAutoAdd(ROOT::DirAutoAdd_t dirAutoAddFunc); 411 void SetDestructor(ROOT::DesFunc_t destructorFunc); 412 void SetImplFileName(const char *implFileName) { fImplFileName = implFileName; } 413 void SetMerge(ROOT::MergeFunc_t mergeFunc); 414 void SetResetAfterMerge(ROOT::ResetAfterMergeFunc_t resetFunc); 415 void SetNew(ROOT::NewFunc_t newFunc); 416 void SetNewArray(ROOT::NewArrFunc_t newArrayFunc); 417 TVirtualStreamerInfo *SetStreamerInfo(Int_t version, const char *info=""); 418 void SetUnloaded(); 419 Int_t WriteBuffer(TBuffer &b, void *pointer, const char *info=""); 420 421 void AdoptReferenceProxy(TVirtualRefProxy* proxy); 422 void AdoptStreamer(TClassStreamer *strm); 423 void AdoptMemberStreamer(const char *name, TMemberStreamer *strm); 424 void SetMemberStreamer(const char *name, MemberStreamerFunc_t strm); 425 void SetStreamerFunc(ClassStreamerFunc_t strm); 426 427 // Function to retrieve the TClass object and dictionary function 428 static void AddClass(TClass *cl); 429 static void RemoveClass(TClass *cl); 430 static TClass *GetClass(const char *name, Bool_t load = kTRUE, Bool_t silent = kFALSE); 431 static TClass *GetClass(const type_info &typeinfo, Bool_t load = kTRUE, Bool_t silent = kFALSE); 432 static VoidFuncPtr_t GetDict (const char *cname); 433 static VoidFuncPtr_t GetDict (const type_info &info); 434 435 static Int_t AutoBrowse(TObject *obj, TBrowser *browser); 436 static ENewType IsCallingNew(); 437 static TClass *Load(TBuffer &b); 438 void Store(TBuffer &b) const; 439 440 // Pseudo-method apply to the 'obj'. In particular those are used to 441 // implement TObject like methods for non-TObject classes 442 443 Int_t Browse(void *obj, TBrowser *b) const; 444 void DeleteArray(void *ary, Bool_t dtorOnly = kFALSE); 445 void Destructor(void *obj, Bool_t dtorOnly = kFALSE); 446 void *DynamicCast(const TClass *base, void *obj, Bool_t up = kTRUE); 447 Bool_t IsFolder(void *obj) const; 448 inline void Streamer(void *obj, TBuffer &b, const TClass *onfile_class = 0) const 449 { 450 // Inline for performance, skipping one function call. 451 (this->*fStreamerImpl)(obj,b,onfile_class); 452 } 453 454 ClassDef(TClass,0) //Dictionary containing class information 455 }; 456 457 namespace ROOT { 458 459 #ifndef R__NO_CLASS_TEMPLATE_SPECIALIZATION 460 template <typename T> struct IsPointer { enum { kVal = 0 }; }; 461 template <typename T> struct IsPointer<T*> { enum { kVal = 1 }; }; 462 #else 463 template <typename T> Bool_t IsPointer(const T* /* dummy */) { return false; }; 464 template <typename T> Bool_t IsPointer(const T** /* dummy */) { return true; }; 465 #endif 466 467 template <typename T> TClass* GetClass( T* /* dummy */) { return TClass::GetClass(typeid(T)); } 468 template <typename T> TClass* GetClass(const T* /* dummy */) { return TClass::GetClass(typeid(T)); } 469 470 #ifndef R__NO_CLASS_TEMPLATE_SPECIALIZATION 471 // This can only be used when the template overload resolution can distringuish between 472 // T* and T** 473 template <typename T> TClass* GetClass( T** /* dummy */) { return GetClass((T*)0); } 474 template <typename T> TClass* GetClass(const T** /* dummy */) { return GetClass((T*)0); } 475 template <typename T> TClass* GetClass( T* const* /* dummy */) { return GetClass((T*)0); } 476 template <typename T> TClass* GetClass(const T* const* /* dummy */) { return GetClass((T*)0); } 477 #endif 478 479 extern TClass *CreateClass(const char *cname, Version_t id, 480 const char *dfil, const char *ifil, 481 Int_t dl, Int_t il); 482 } 483 484 #endif // ROOT_TClass 485