A. Vosch
A. Vosch

Reputation: 23

C++ comparing pointers using multiple-inheritance with unknown base class

I have got two std::vectors of pointers to classes A and B and am trying to make a method that removes an object from those vectors. This Object may or may not be a subclass of A and/or B and does not have to be an Element of any of the vectors. I have tried following code:

void removeObject(void *object) {
    A *pa = static_cast<A*>(object);
    std::vector<A*>::iterator aPos = std::find(as.begin(), as.end(), pa);
    if (aPos != as.end())
        as.erase(aPos);
    B *pb = static_cast<B*>(object);
    std::vector<B*>::iterator bPos =  std::find(bs.begin(), bs.end(), pb);
    if (bPos != bs.end())
        bs.erase(bPos);
}

but the pointers have different values, so std::find doesn't work (or rather it works sometimes). After reading Multiple inheritance pointer comparison and C++ pointer multi-inheritance fun I understand why, but in both cases the suggested solution was to cast the pointer to *subclass. My questions are:

  1. How can I check whether two pointers refer to the same object without knowing its type?
  2. Is there a more elegant solution to my problem?

I am new to C++ so please excuse me if I have thoroughly misunderstood something...

Upvotes: 2

Views: 852

Answers (2)

Jonathan Mee
Jonathan Mee

Reputation: 38919

void* is an old C concept in C++ you want to know what type you're working with because that's the foundation of template programming. To that end lets change your function signature to:

template <typename T>
void removeObject(T* object);

From here we can use is_base_of to identify whether the type is a base of the elements of each vector's value_type:

if(is_base_of_v<T, decltype(as)::value_type>) {
    auto aPos = find(cbegin(as), cend(as), *static_cast<A*>(object));

    if(aPos != cend(as)) as.erase(aPos);
}

if(is_base_of_v<T, decltype(bs)::value_type>) {
    auto bPos = find(cbegin(bs), cend(bs), *static_cast<B*>(object));

    if(bPos != cend(bs)) bs.erase(bPos);
}

Obviously, the static_cast would be completely illegal if object was a pointer to an actual base class. I'm assuming that even though though object is a pointer to a base class it's really of the type it's being static_cast to, otherwise we need to go back to the drawing board.

Upvotes: 1

Alan Stokes
Alan Stokes

Reputation: 18964

If your classes are polymorphic (have at least one virtual function) then dynamic_cast<void *>() will return a pointer to the beginning of the most-derived object - so it will always return the same answer for the same object even if you start from pointers to unrelated base classes.

But if you have already converted the pointer you had to void * it's too late for that. You might be better off just storing pointers to some common base class.

Upvotes: 3

Related Questions