Adding a class template to ROOT problem

Dear all,

after reading this howto: root.cern.ch/drupal/content/addi … t-classdef. I would like to add two classes to ROOT.

First ClassA is templete class and looks just like:

[code]#ifndef ClassA_h
#define ClassA_h

#include “TObject.h”

template
class ClassA: public TObject{ // ClassA is derived from TObject
private:
Value fValue;

public: 
    ClassA(){};                     // default constructor
    virtual ~ClassA(){};          // virtual destructor
ClassDef(ClassA,1)          // ClassDef macro...

};

#endif [/code]

and the second ClassB looks like:

[code]#ifndef ClassB_h
#define ClassB_h

#include “TNamed.h”
#include “ClassA.h”

class ClassB: public TObject{ // ClassB is derived from TObject
private:
ClassA<TNamed*> fVariable;

public:
    ClassB(){};                  // default constructor
    virtual ~ClassB(){};      // virtual destructor
ClassDef(ClassB,1)       // ClassDef macro...

};

#endif[/code]

But I can’t get it working:

root [0] .L ClassA.h++g Info in <TUnixSystem::ACLiC>: creating shared library /data/usr/jiri/Desktop/rootProblem/./ClassA_h.so root [1] .L ClassB.h++g Info in <TUnixSystem::ACLiC>: creating shared library /data/usr/jiri/Desktop/rootProblem/./ClassB_h.so dlopen error: /data/usr/jiri/Desktop/rootProblem/./ClassB_h.so: undefined symbol: _ZN6ClassAIP6TNamedE11ShowMembersER16TMemberInspectorPc Load Error: Failed to load Dynamic link library /data/usr/jiri/Desktop/rootProblem/./ClassB_h.so /usr/lib/gcc/x86_64-unknown-linux-gnu/4.4.3/../../../../lib/crt1.o: In function `_start': (.text+0x20): undefined reference to `main' /data/usr/jiri/Desktop/rootProblem/./ClassB_h_ACLiC_dict.o: In function `ClassB::ShowMembers(TMemberInspector&, char*)': ClassB_h_ACLiC_dict.cxx:(.text+0x413): undefined reference to `ClassA<TNamed*>::ShowMembers(TMemberInspector&, char*)' /data/usr/jiri/Desktop/rootProblem/./ClassB_h_ACLiC_dict.o:(.data.rel.ro._ZTV6ClassAIP6TNamedE[vtable for ClassA<TNamed*>]+0x1d0): undefined reference to `ClassA<TNamed*>::ShowMembers(TMemberInspector&, char*)' /data/usr/jiri/Desktop/rootProblem/./ClassB_h_ACLiC_dict.o:(.data.rel.ro._ZTV6ClassAIP6TNamedE[vtable for ClassA<TNamed*>]+0x1d8): undefined reference to `ClassA<TNamed*>::Streamer(TBuffer&)' /data/usr/jiri/Desktop/rootProblem/./ClassB_h_ACLiC_dict.o: In function `ClassA<TNamed*>::IsA() const': ClassB_h_ACLiC_dict.cxx:(.text._ZNK6ClassAIP6TNamedE3IsAEv[ClassA<TNamed*>::IsA() const]+0xd): undefined reference to `ClassA<TNamed*>::Class()' collect2: ld returned 1 exit status *** Interpreter error recovered ***

So something is wrong with linking…

What one has to do to add these two classes to ROOT?
What is the problem? :slight_smile:

(ROOT: 5.26/00b)

Thank you in advance,
Jiri

Hi Jiri,

The problem is that the directory for the specific instance of your template is not being generated. You need to add #ifdef __MAKECINT__ #pragma link C++ class ClassA<TNamed*>+; #endifto ClassB.h (or ClassA.h if you prefer to associate the dictionary for the instance with ClassA_h.so)

Cheers,
Philippe.

Hi Philippe,

Super, it works now :slight_smile:

Just one question:

Is it possible to generate the dictionary for “all” classes known to ROOT or is necessary to specify each specific instance of the teplate:

#ifdef __MAKECINT__ #pragma link C++ class ClassA<TNamed*>+; #pragma link C++ class ClassA<Double_t>+; ... #pragma link C++ class ClassA<ClassTwoThousand*>+; ... #endif

?

Cheers,
Jiri

Hi Jiri,

You have to specify each instance (otherwise you will get both an explosion in the size of the dictionary and compilation error as not every type is a good candidate for instantiating your template).

Cheers,
Philippe.

Hi Philippe,

ok, problem solved :slight_smile:

Thank you very much again,
Jiri