Re: ROOT containers: do they need to know about gROOT ?

Fons Rademakers (Fons.Rademakers@cern.ch)
Tue, 17 Mar 1998 13:01:06 +0100


Hi Pasha,

in principle the ROOT containers could be made completely independent
of the initialization of TROOT. Currently TROOT is only needed in case
of an Error or Warning. What happens is that TObject::Error() (or Warning()
or Fatal()) call the ROOT RTTI to find out the real classname of the object
calling the Error() function. This to give the printout (<TObjArray::At>...).
This can be fairly easily changed.

Further, TObject::IsEqual() does not require ROOT RTTI. The default
implementation of IsEqual() is:

//______________________________________________________________________________
Bool_t TObject::IsEqual(TObject *obj)
{
// Default equal comparison (objects are equal if they have the same
// address in memory). More complicated classes might want to override
// this function.

return obj == this;
}

and this just compares pointers.

However, derived classes could override IsEqual() and use ROOT RTTI.
For example:

//______________________________________________________________________________
Bool_t TObjString::IsEqual(TObject *obj)
{
if (this == obj) return kTRUE;
if (TObjString::Class() != obj->IsA()) return kFALSE;
return fString == ((TObjString*)obj)->fString;
}

Here we need to test the class type of "obj" before we can make a
valid cast to TObjString*. This requires ROOT RTTI. However, in ANSI C++
we don't need the ROOT RTTI in this case and could use the C++ RTTI:

//______________________________________________________________________________
Bool_t TObjString::IsEqual(TObject *obj)
{
if (this == obj) return kTRUE;
TObjString *os = dynamic_cast<TObjString*>(obj);
if (!os) return kFALSE;
return fString == os->fString;
}

hence IsEqual() or TOrdCollection do not require the ROOT RTTI and
TROOT being initialized.

So in summary, I'll try to remove TROOT dependency from Error(), etc.
and the user classes should not use ROOT RTTI in IsEqual() to be TROOT
independent.

Cheers, Fons.

Pasha Murat wrote:
>
> Hello,
> there is one issue which could be of interest for general discussion.
> ROOT has a pretty nice set of collection classes and I've been asked several
> times whether it is possible to use them outside the context of ROOT (means
> without TROOT object being initialized in the code.)
>
> Trying to find an answer I realized that some of the container
> classes (like TObjArray) could be used outside ROOT, others (like TOrdCollection)
> require TROOT object to be initialized.
>
> The thing which confuses me a little bit is the following.
> TOrdCollection class uses RTTI when TOrdCollection::IndexOf(TObject *obj)
> tries to define location of the object in the list. Here is its source
> code (taken from 1.03/09):
> --------------------------------------------------------------------------------
> Int_t TOrdCollection::IndexOf(TObject *obj) const
> {
> // Return index of object in collection. Returns -1 when object not found.
> // Uses member IsEqual() to find object.
>
> for (Int_t i = 0; i < GetSize(); i++)
> if (fCont[PhysIndex(i)]->IsEqual(obj))
> return i;
>
> return -1;
> }
> --------------------------------------------------------------------------------
> TOrdCollection::IsEqual calls ROOT RTTI.
>
> Given the collection contains pointers to TObjects, why is it necessary to
> use RTTI when comparing TObject* to TObject* ? Isn't it enough just to compare
> to pointers to each other? Or this is related to ROOT I/O and persistency
> mechanism?
>
> Thanks, Pasha.

-- 
Org:    CERN, European Laboratory for Particle Physics.
Mail:   1211 Geneve 23, Switzerland          Phone: +41 22 7679248
E-Mail: Fons.Rademakers@cern.ch              Fax:   +41 22 7677910