User defined IsEqual function with THashTable


I’m trying to use a THashTable just to check whether or not an integer belongs to a set of integers. I’m not sure if this will end up being the fastest way to do it in my case but I wanted to check and see. If there’s way to do this with less overhead in ROOT then I would be happy to hear about it. In the meantime, I’m having trouble checking whether an integer has been added to the hash table. Here’s a code example:

class Integer : public TObject {
    ULong_t i;
    Integer(ULong_t ival) { i = ival; }
    ULong_t Hash() const { return i; }
    Bool_t IsEqual(const TObject* obj) { 
        cout << Hash() << "\t" << ((Integer*)obj)->Hash() << endl;
        return Hash() == ((Integer*)obj)->Hash(); }

    ClassDef(Integer, 1) //just holds an integer...

void example() {
    THashTable hash(20, 2);
    Integer a(4);
    Integer b(12);
    Integer c(4);
    cout << "a check: " << hash.FindObject(&a) << endl;
    cout << "b check: " << hash.FindObject(&b) << endl;
    cout << "c check: " << hash.FindObject(&c) << endl;

which produces this output:

root.exe [0] 
Processing example.C...
a check: 0x8e65c60
b check: 0x8e6f500
c check: 0

I want the third FindObject call to find a because a and c are identical as far as I care. When I look through the code it looks like FindObject is eventually using IsEqual to determine if the objects are equal but when I run this it doesn’t appear to call Integer::IsEqual(). I think this is because THashTable is casting the pointer to TObject before passing it along which is making it use TObject::IsEqual instead? Is it possible to use my own IsEqual function with THashTable?


You overloaded TObject::IsEqual incorrectly. Its signature is

Bool_t TObject::IsEqual(const TObject*) const;

while you create an overload

Bool_t Integer::IsEqual(const TObject*);

The fact that TObject’s function was const becomes part of its signature. Since your overload isn’t const you created a new (different) function. This function will not be found when calling the virtual TObject::IsEqual on a TObject pointer. Clang++ or newer GCC compilers have a warning for this.

The solution is to change your function signature to

Bool_t Integer::IsEqual(const TObject*) const;

On an unreleated note, I doubt that wrapping a simple integer datatype in a TObject to put int a THashTable while give you a faster hash table then the simple C++ solution with a std::set (or better std::unordered_set).

Thanks, you were right. I had originally written it using std::unordered_set but need to deploy on machines with an older version of gcc that doesn’t have support for this. I thought it was possible that THashTable would give better performance than std::set despite the overhead so I figured it wouldn’t hurt to check it.