12

The below code explains the problem. Fill in same_sub_class to detect if the two pointers to virtual base class A are in fact the same concrete class.

struct A {
    ...
}:

struct B : public A {
    ...
}:

struct C : public A {
    ...
}


bool same_sub_class(A * a1, A * a2){
    // Fill this in to return true if a1 and a2 are
    // of the same concrete class
}

EDIT:

As I look at my application I need something slightly different from the above. I need to be able to group instances by their type_id.

FYI. I have a mini symbolic algerbra system so to do manipulations it is important to know the class type sometimes for sorting, and rearranging expressions.

So given a vector of pointers to instance how to group them by their type_id. I'd either need to be able to hash the type_id or generate a unique integer for every class.

1
  • 1
    sounds like what you really need is a static int on each class to sort by? Commented Oct 5, 2010 at 14:54

6 Answers 6

22

If you can use RTTI,

typeid(*a1) == typeid(*a2)

I think you also need to

#include <typeinfo>

And you must have a virtual function in your classes so that the vtable exists--a destructor should do fine.

UPDATE:

I'm not sure I completely understand what your requirements are for grouping (Do you need some kind of deterministic ordering? What should happen with sub-subclasses?), but you could try using the value returned from the typeid operator to either:

  • Hash the string returned from typeid(*ptr).name()
  • Use typeid(*a1).before(typeid(*a2)) as an ordering criterion. This doesn't have any determinism between runs, though.

Generally when considering RTTI, it is a good idea to see if any of this can be accomplished better using well-crafted virtual functions (double dispatch, for example). I really can't say if there is a good alternative in your case though, since I don't understand the specifics.

Sign up to request clarification or add additional context in comments.

8 Comments

You need to remember to include <typeinfo> as well.
But A has to be polymorphic isn't??
@liaK, yes, the base class must have at least one virtual function.
@Tim thanks for that. I've made an edit to the question to better reflect the problem I'm trying to solve. Turns out that simple equality is not quite what I need.
"Hash the string returned from typeid(*ptr).name()" - Ouch! Let's see: OP has to have at least one virtual function anyway, for typeid to work. Isn't adding a virtual function that returns type_id as simple int the easiest way?
|
10
typeid(*a1) == typeid(*a2)

Note the dereference, it is important.

Comments

2

You could make your own type Identifier:

struct A{
...
protected:
 enum TypeTag{B_TYPE, C_TYPE};
 TypeTag typeTag;
};

And then in constructors of subclasses:

B::B()
: typeTag(TypeTag::B_TYPE)
{
...
}

C::C()
: typeTag(TypeTag::C_TYPE)
{
...
}

7 Comments

typeTag better be private. Not enum but variable.
@Manoj: i disagree. typeTag is initialized in the sublasses constructor, so it can't be private member of base class.
@Adesit: typeTag must be protected. But this mechanism is not perfect, because on adding new descendant we need to add new member of enum. Best regards to Odessa :)
I think it's a bad idea, better to use RTTI
@piotr Its not fair to simply say "this bad" unless you provide a reason. I dont know it for sure, but i think my idea is kind of what rtti is inside. Generally speaking, most of the time its good to stick to the standard, but sometimes its better to implement something yourself. We dont know the exact circumstances of the poster. Consider for example, that rtti is not supported under Android NDK.
|
2

Actually there are a fairly simple answers to this. But it involves posing the questions a bit clearer.

(A) If I want to store typeinfo objects in an unordered_set what do I need to do?

typeinfo support the == and the name() method. The name can be used to generate a hash and == for equality

(B) If I want to store typeinfo objects in an ordered_set ( std::set ) what do I need to do?

typeinfo supports the == and the before() method. With bit of wrapping of these two methods I can implement an interface for a Compare function that gives me strict weak ordering.

Comments

1

There is a feature in C++ called RTTI (runtime type information) which allows you to do such things.

One other possibility to have runtime type checking is to create a base class from which all your classes derive from. In your base class include a field which contains its type as a string or a number.

Comments

0

One trick that may or may not work with RTTI, depending on your compiler, is the following

const type_info &a1_type_info= typeid(*a1);
const type_info &a2_type_info= typeid(*a2);

return &a1_type_info==&a2_type_info || a1_type_info==a2_type_info;

If your compiler creates type_info instances by value, this will fail the first test but succeed on the second test. If your compiler caches the instances, the first test will succeed (if it's the same type) and be much faster since it's just a pointer compare. If your compiler returns different instances because a1 and a2 came from different shared libraries, it should still work.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.