Hello, I am stumped while trying to compile a class with more than one template argument. I have made up ClassDefTT, ClassDefTT2, ClassImpTT2 macros in analogy to the corresponding ones for the single-argument template classes. Everything almost works, except that the declaration of a friend operator function seems to exercise a bug in CINT. A trivial example that reproduces the problem is attached in several files: test.h, test.cxx, ClassDefTT.h, and LinkDef.h. These compile and work under g++. I am using ROOT v3.00.02 (also tried 3.00.05) on a Linux SUSE 6.1 box, upgraded to the 2.4.1 kernel. The reason that I am fairly sure that this is a CINT bug is that if I give a default argument to the class U, e.g., replace the third line in the test.h file with template<class T, class U=T> class A; and replace all A<T, U> with A<T> (so that U now having the default value above), rootcint correctly generates the CINTDict file. The rootcint command line is rootcint -f CINTDict.cxx -c -p -I. -I${ROOTSYS}/include test.h LinkDef.h The messages I get from rootcint are, class A<int,int> in test.h line 9 original base of virtual func Note: Link requested for undefined class const FILE: LINE:0 Note: Link requested for undefined class int>operator+<>(constA<int,int>&,int&) FILE: LINE:0 Class const: Streamer() not declared Class const: ShowMembers() not declared Class int>operator+<>(constA<int,int>&,int&): Streamer() not declared Class int>operator+<>(constA<int,int>&,int&): ShowMembers() not declared Class int>operator+<>(constA<int,int>&,int&): Class_Name() and initialization object not declared Thanks for any help. Regards, Gora #include <Rtypes.h> #include <ClassDefTT.h> template<class T, class U> class A; template<class T, class U> const A<T, U> operator+(const A<T, U>&, U&); template<class T, class U> class A { private: T i; public: A(T ii = 0) : i(ii) {} friend const A<T, U> operator+ <>(const A<T, U>&, U&); ClassDefTT(A, 1) }; ClassDefTT2(A, T, U) // #include <iostream> #include "test.h" ClassImpTT(A, T, U) template<class T, class U> const A<T, U> operator+(const A<T, U>& a, U& b) { return A<T, U>( a.i + b ); } // Include file for template classes with two parameters. Adapted from // Rtypes.h. #ifndef ClassDefTT_INC #define ClassDefTT_INC //---- ClassDefTT macros for templates with two parameters ---------------- // ClassDefTT corresponds to ClassDef // ClassDefTT2 goes in the same header as ClassDefT but must be // outside the class scope // ClassImpTT corresponds to ClassImp extern void AddClass(const char *, Version_t, VoidFuncPtr_t, Int_t); extern void RemoveClass(const char *); #define ClassDefTT(name,id) \ private: \ static TClass *fgIsA; \ public: \ static TClass *Class(); \ static const char *Class_Name(); \ static Version_t Class_Version() { return id; } \ static void Dictionary(); \ virtual TClass *IsA() const { return name::Class(); } \ virtual void ShowMembers(TMemberInspector &, char *); \ virtual void Streamer(TBuffer &); \ void StreamerNVirtual(TBuffer &b) { name::Streamer(b);} \ static const char *DeclFileName() { return __FILE__; } \ static int DeclFileLine() { return __LINE__; } \ static const char *ImplFileName(); \ static int ImplFileLine(); #define _ClassInitTT_(name,Tmpl_A,Tmpl_B) \ template <class Tmpl_A, class Tmpl_B> class _NAME2_(R__Init,name) { \ public: \ _NAME2_(R__Init,name) (Int_t pragmabits) { \ AddClass(name<Tmpl_A, Tmpl_B>::Class_Name(), \ name<Tmpl_A, Tmpl_B>::Class_Version(), \ &name<Tmpl_A, Tmpl_B>::Dictionary, pragmabits); \ } \ _NAME3_(~,R__Init,name) () { \ RemoveClass(name<Tmpl_A, Tmpl_B>::Class_Name()); \ } \ }; #define ClassDefTT2(name,Tmpl_A,Tmpl_B) \ template <class Tmpl_A, class Tmpl_B> \ TBuffer &operator>>(TBuffer &, name<Tmpl_A, Tmpl_B> *&); \ _ClassInitTT_(name,Tmpl_A,Tmpl_B) #define _ClassImpTT_(name,Tmpl_A, Tmpl_B) \ template <class Tmpl_A, class Tmpl_B> \ TClass *name<Tmpl_A, Tmpl_B>::Class() \ { if (!fgIsA) name<Tmpl_A, Tmpl_B>::Dictionary(); return fgIsA; } \ template <class Tmpl_A, class Tmpl_B> \ const char *name<Tmpl_A, Tmpl_B>::ImplFileName() { return __FILE__; } \ template <class Tmpl_A, class Tmpl_B> \ int name<Tmpl_A, Tmpl_B>::ImplFileLine() { return __LINE__; } \ template <class Tmpl_A, class Tmpl_B> \ TClass *name<Tmpl_A, Tmpl_B>::fgIsA = 0; #define ClassImpTT(name,Tmpl_A, Tmpl_B) \ template <class Tmpl_A, class Tmpl_B> \ void name<Tmpl_A, Tmpl_B>::Dictionary() { \ TClass *c = CreateClass(Class_Name(), Class_Version(), \ DeclFileName(), ImplFileName(), \ DeclFileLine(), ImplFileLine()); \ fgIsA = c; \ } \ _ClassImpTT_(name,Tmpl_A, Tmpl_B) #endif // #ifndef ClassDefTT_INC //@@@@@@@@@@@@@@@@@@@@@@@@@ END OF FILE @@@@@@@@@@@@@@@@@@@@@@@@@ #ifdef __CINT__ #pragma link off all globals; #pragma link off all classes; #pragma link off all functions; #pragma link C++ class A<Int_t, Int_t>; #endif
This archive was generated by hypermail 2b29 : Tue Jan 01 2002 - 17:50:37 MET