Reputation: 23
I have got two std::vector
s 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:
I am new to C++ so please excuse me if I have thoroughly misunderstood something...
Upvotes: 2
Views: 852
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
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