RE: Templated member functions in root.

From: Philippe Canal <pcanal_at_fnal.gov>
Date: Wed, 16 Feb 2005 09:17:12 -0600


Hi Brett,

Currently the interpreter in unable to instantiate __automatically__ the templated members functions. The simple solution (if it is feasible) it to request explictly the dictionary for those functions. For example:

#pragma link C++ function HistMan::Book<TH1D>(const char*, ....etc... );

Note that this can be done in a dictionary separate from the main HistMan dictionary.

If this is not practical (for example if the user is expected to use Book with any arbitrary template parameter), you will need to study in detail the technique used to implement the dictionary entry for TDirectory::GetObject, TDirectory::WriteObject, TTree::Branch and TTree::SetAddress (see base/src/ManualBase4.h and tree/src/ManualTree2.cxx)

Cheers,
Philippe.

-----Original Message-----
From: owner-roottalk_at_pcroot.cern.ch [mailto:owner-roottalk_at_pcroot.cern.ch] On Behalf Of Brett Viren
Sent: Tuesday, February 15, 2005 5:50 PM To: roottalk_at_pcroot.cern.ch
Subject: [ROOT] Templated member functions in root.

Hi,

I have a class that has a few templated member functions that don't seem work in interpreted code. The full code can be browsed here:

http://minos.phy.bnl.gov/~bviren/minos/software/hm/HistMan/

This is a helper class that provides a simple histogram manager. It all works well in compiled code and non-templated methods work in interprete code, but templated methods don't. The actual implementation is a manually compiled library (not ACLiC) that is gSystem->Load()ed into a root session.

The meat of the problem can be seen by looking at the Book<>() method which is templated in order to assure type safety.

class HistMan {
public:
...

    /// Book 1D or 2D histograms of type THType.  Return pointer to created
    /// histogram (HistMan retains ownership) or 0 if "path/name"
    /// conflicts with previously existing histogram.
    template<class THType>
    THType* Book(const char* name, const char* title,
                 int nbinsx, Axis_t xmin, Axis_t xmax,
                 const char* path=".") {
        TH1* h = Adopt(path, new THType(name,title,nbinsx,xmin,xmax));
        return dynamic_cast<THType*>(h);
    }
...

};

This is supposed to be used like:

  HistMan hm("path");
  TH1D* h = hm.Get<TH1D>("h","hist",100,0,10);

but which produces the following in root:



root [0] gSystem->Load("libHistMan")
(int)0

root [1] HistMan hm("foo")
root [2] TH1D* h = hm.Book<TH1D>("h","hist",100,0,10); Error: Symbol hm is not defined in current scope FILE:(tmpfile) LINE:1 Error: Failed to evaluate hm.BookError: Symbol TH1D is not defined in current scope FILE:(tmpfile) LINE:1
*** Interpreter error recovered ***
root [3] hm
(class HistMan)150525008

root [4] hm.BaseFolder()
(class TFolder)150648744

Note that the object itself and non-templated methods (this one returns a reference to the underlying folder holding the histograms) work as well.

So, my question is: should this be expected to work, and if so what might I be doing wrong.

ROOT 4.01/05, GCC 3.3.5 x86 Debian.

Thanks,
-Brett. Received on Wed Feb 16 2005 - 16:19:15 MET

This archive was generated by hypermail 2.2.0 : Tue Jan 02 2007 - 14:45:05 MET