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