Adding Class to Root inside namespace

Hello all,

I am trying to add a class to get Root functionalities but I am not being fortunate to do so…

I’ve searched a lot the documentation and exhausted internet search resources without being able to solve my problem, I come here as the last resource.

So, I have something like this (inside Athena framework):

namespace Ringer {

  // Declare interface base for all Ringer procedure types:
  class IRingerProcedure : public TClass {                      
    //public:
      //virtual ~IRingerProcedure(){;}
    //protected: 
      //IRingerProcedure(){;} 

      /** Define it as a Root TObjebt, disable I/O */
      ClassDef(Ringer::IRingerProcedure,0)
      // Also tried ClassDef(IRingerProcedure,0) and ClassDef(IRingerProcedure,1)
  };
}

The destructor and ctor are commented but I’ve also tried with them uncommented (in fact, the original implementation uses the ctor as protected to ensure that this class is abstract, but anyway, all I want is it to work first), but none worked.

I’ve tried to add the dtor and ctor implementations because I read that the destructor should be virtual https://root.cern.ch/drupal/content/adding-your-class-root-classdef#why and the user manual says that the object I/O (I know that this is not the case, because I disabled it, but anyway) will need one implementation of ctor that he can use (I’ve used it as public as well). But yes, they are inlined: is it a problem?

This class is inherited by many others, all of them complaining that they couldn’t find the vtable for this (and many other) class(es).

So, I’ve also tried to add ClassImp on a .cxx including this file, and tried to do ClassImp(Ringer::IRingerProcedure) and its version without namespace.

I am using genreflexdict, with the selection file as:

<lcgdict>

<enum pattern="Ringer::*"/>
<class pattern="Ringer::*" />

<!-- Remove extra Root catchups by above patterns -->
<exclusion>
<class pattern="*ROOTDict::*" />
</exclusion>                                               

And in the dict header file I include the files needed.

If you can’t help me with the details, is it possible for you to inform me how to handle ClassDef and (template)ClassImpl when my class/template is within namespace and if it is supposed to work within abstract (or even empty) classes/templates or how should I work with them in that case.

Edit: I’ve forgotten to mention, I think I don’t need the ClassImpl functionalities, as it seems to add only the Html documentation support (which is not needed).

In advance,
Werner.

Hi Werner,

before diving into the details: what is the problem which drives you to design an interface (in the Gaudi language) and to make it inherit from TClass?

Cheers,
Danilo

Hi Danilo,

In short lines: I want to take advantage of Root I/O. I have other possibilities (work with TEnv, or save it into a python configuration file) to work with, but it would be easier and a more harmonic solution (since I wouldn’t need to implement any I/O workaround).

More detailed explanation:

Usually the data is read through txt file (TEnv). In this package being developed, there will be several different configuration data that will be divided in different levels, i.e.:

-> Classifier1:
—> PreProcessors (may be absent):
——> PreProp1Data
——> PreProp2Data

——> PrePropNData
—> ClassifierData
—> ThresholdData (empty for this classifier).
-> Classifier2 (same as above, but with its own data)

-> ClassifierN (again, but last classifier needs a threshold)

Of course, I can do that the usual way (using TEnv), but I thought why shouldn’t I use the Root I/O instead? That would be great if I made use of what Root have developed for I/O instead having to save it into text file and making this I/O routine, even if TEnv and some routines available would help me with that. The data saved would be quite more encapsulated (and maybe compressed, even though this isn’t that important), and held in the exact structure that it will be used. I could save a nested TList with those objects, and just read it on the Athena-Gaudi environment. This would save many lines in my code, would make it quite cleaner (easier to understand) and optimal in the lines that I won’t write a txt file and have everything done by Root I/O that is much more reliable than what I would write.

So, it would be much better to take advantage to Root I/O for these objects, I would save them after adjusting their weights and read this file afterwards to run my classifiers.

Cheers,
Werner.

[quote=“dpiparo”]Hi Werner,

before diving into the details: what is the problem which drives you to design an interface (in the Gaudi language) and to make it inherit from TClass?

Cheers,
Danilo[/quote]

Hi Werner,

I am happy you want to take advantage of the ROOT IO :slight_smile: and I think it’s a good idea.
On the other hand I would have two objections:

  1. names like IRingerProcedure are usually reserved to interfaces (pure virtual) in the Gaudi world. What you are trying to achieve is not a virtual interface.
  2. In order to perform IO with objects, you just need a dictionary for them. This does not prevent you from inheriting from TObject: it can be really handy. On the other hand inheriting from TClass is a mistake.

Cheers,
Danilo

Hi Danilo,

  1. well, that was something I was not sure… this class is inherited by many interfaces which led me to call it like that, but since it won’t be used as an interface I think you are right… this is a misleading name. I will change it to RingerProcedureBase. Thanks for making me rethinking of it.

  2. Yes, I read it on TFile documentation (https://root.cern.ch/root/html/TDirectoryFile.html#TDirectoryFile:Get) after I started getting lost, but I was so bored that I couldn’t make my class a TClass… there are other Gaudi applications that are able to do so. Anyway, I am getting the point, all I need is to use Root I/O and add ClassDef to my objects if I want to help Root in the file lookup as it is said here:

[quote]Why ClassDef?

You must use it if your class derives from TObject. You can use it even if not. It enables features like ROOT’s introspection mechanism (obj->IsA() returning a TClass*). And it increases the I/O speed, even though ROOT I/O will also work without. The amount of that speed improvement depends on so many things that we cannot give a precise number; it saves a map lookup per object stored.[/quote]

Keeping this in mind, I removed the inheritance from all interfaces from TObject and only added ClassDef to those classes that have implementation, and it worked :smiley: (well, at least compiled). Then, I tried to add ClassDef to one of the most outer Interfaces I have, and it gave me undefined references library compilation issue. It seems that I can’t add ClassDef even if I set it to version 0 to interfaces.

Continuing the practical exercise to find what I am able to do, I first added TObject inheritance to one non interface class and it worked. Then, I changed the TObject inheritance to this class interface, now without setting a ClassDef to it, and it also compiled. Afterwards I also removed ClassDef from the non interface class and it also compiled, which made me confused. Shouldn’t I get a compilation error? Or this will turn into an issue when I try to read this TObject without ClassDef?

Is it ok if I put the base of all classes (RingerProcedureBase) as a TObject and only put ClassDef on those classes that are not pure virtual? Or it is better to inherit from TObject only when the class is not pure virtual?

Sorry for so many doubts… and thank you for being helpful x)

Hi Werner,

maybe a small example could help to clarify the issue.
Could you provide a schematic view of your class federation? A simple header with the classes w/o any method/member and the selection file will do.

Cheers,
Danilo