tags:

views:

90

answers:

6

This is my code:

class Base { /* something */ };
class Derived : public Base { /* something */ };
vector<Base*> v; // somebody else initializes it, somewhere
int counter = 0; 
for (vector<Base*>::iterator i=v.begin(); i!=v.end(); ++i) {
  if (typeof(*i) == "Derived") { // this line is NOT correct
    counter++;
  }
}
cout << "Found " << counter << " derived classes";

One line in the code is NOT correct. How should I write it properly? Many thanks in advance!

A: 

I think typeof is only available in C#.

The SO post "How to typeof in C++" may be of use ...

Update: This may be of use:

The typeof operator, AFAIK, was a GCC extension. It no longer works on templated objects as of GCC 3.2.3. Bug report: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=9459

Release changes: http://www.gnu.org/software/gcc/gcc-3.2/changes.html

Currently GCC seems to have a really hard time determining the type of template functions even in legitimate circumstances...

And I think GCC supports the __typeof__ operator.

And as others have stated, I guess you can use typeid as a replacement.

Jacob
Thanks for suggestions, but the question is how I can make COMPARISON. I don't need just typeid information. I need an ability to compare it with a string. Thanks
Vincenzo
A: 

Take a look on typeid operator.

In general, it's considered a bad idea to use it.

a1ex07
Alex, what is a good alternative to it? Thanks
Vincenzo
Using dynamic_cast is better, but anyway, usually you don't need to know exact type of the object. All logic can be implemented by virtual functions. However, sometimes you need to know exact type, and in such cases you have to use typeid.
a1ex07
+5  A: 

Use dynamic_cast:

if ( dynamic_cast <Derived*>( *i) ) { 
    counter++;

For this to work, you will need to give your base class at least one virtual function - it really needs a virtual destructor anyway.

anon
A: 

You can either use typeid (include <typeinfo>):

if (typeid(**i) == typeid(Derived))

or you can use a dynamic cast:

if (dynamic_cast<Derived*>(*i) != 0)

but both codes should generally be avoided in favour of a virtual function that is called and that is overridden to perform the appropriate action for each type.

Konrad Rudolph
Are you sure that the last bit of advice applies here. Why should one write a virtual function to emulate the same RTTI that is already available (except leaves less room for errors)?
UncleBens
@UncleBens: How can I be sure if all we have is a toy example code? But I’m sure that in the vast majority of use-cases, yes, my last bit of advice applies. And even in the toy example a case could be made for a virtual `isDerived` function that is used in conjunction with `count_if`.
Konrad Rudolph
Thanks for your comment, Konrad! However, I DON'T have any virtual functions in Base class..
Vincenzo
@Vincenzo: You need to change that anyway. Otherwise, neither `typeof` nor `dynamic_cast` will work. In fact, I don’t really understand your comment …
Konrad Rudolph
It has rather specific content for a toy program... I just don't see what's the point of having RTTI at all, if it shouldn't be used even if the purpose of the program (as far as we can tell) is to identify types at runtime. - It might also be simpler to write a functor/function to be used with `count_if`. - As an exercise it is worth to learn how RTTI works (what's the difference between `typeid` and `dynamic_cast`, how they behave with polymorphic/static types etc.)
UncleBens
@UncleBens: there remain a lot of cases where virtual functions cannot replace `dynamic_cast` and/or `typeid` checks … just as one example, interpreters and compilers require differently typed data to be extracted from a common interface. Virtual functions can’t deliver that very well (the alternative are fat interfaces).
Konrad Rudolph
@Konrad: They *could* define a virtual function that returns an id, and then you can use `static_cast`? Naturally there's no point to reinvent an existing language feature if that's what you need, but that's what I was saying.
UncleBens
@UncleBens: I concede defeat. ;-)
Konrad Rudolph
+5  A: 

The names of typeid are implementation-defined and you shouldn't make assumptions about them. However, you could compare two typeid's.

if typeid(**i) == typeid(Derived)

Generally it would be considered a bad design (but if the purpose is just to write a not very practical program to count instances of Derived, it's just fine).

Note that this also requires Base to have a vtable (virtual functions and/or destructor), because non-polymorphic types just don't have a dynamic type which typeid checks (that is, they would all be instances of Base as far as typeid is concerned).

If you don't have any virtual functions, then you'll need to emulate this yourself. For example, if you like string comparisons and don't mind the overhead, add a field to Base that each type will fill out in its constructor and compare those. Otherwise use a unique integral identifier for each subtype etc.

UncleBens
Thanks, now everything is clear :)
Vincenzo
I found this link: http://www.boost.org/doc/libs/1_42_0/libs/type_traits/doc/html/boost_typetraits/reference/is_same.html. Looks like this library could help..
Vincenzo
@Vincenzo: This works only at compile-time. At compile-time all the static types in the vector are the same. You need a runtime mechanism.
UncleBens
A: 

I think you want:

for (...) {
   if (dynamic_cast<Derived*>(*i)) {
     counter++;
   }
}

dynamic_cast<> tries to convert the base class pointer to a derived-class pointer. If the object is of the derived type (or a subclass of it), the correct pointer is returned. If it is not that derived type it returns 'nil' to indicate that the conversion cannot be done successfully.