Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use dynamic_cast with for_each

I have the following code:

vector<C1*>::iterator itr = vec.begin();
for (; itr != vec.end(); ++itr) {
  C2 *c = dynamic_cast<C2*>(*itr);
  c->f();
}

I am wondering if I could use one-line for_each to replace it. I tried the following:

for_each(vec.begin(), vec.end(), bind2nd(mem_fun(&C2::f), dynamic_cast<C2*>));

But I get a compile error,

expected unqualified-id before 'dynamic_cast'

What should be the right then?

[EDIT] I cannot use c++11. Looks like I have to define an extra functor, sigh.

For some questionings about the code itself: C1 and C2 are 2 pure interfaces; f() is only available as C2's API. The vector "vec" has a list of objects which have both C1 and C2 interfaces, but they are passed to this piece of code as vector of C1*.

like image 262
my_question Avatar asked Jan 03 '14 20:01

my_question


People also ask

Should I use dynamic_cast?

This cast is used for handling polymorphism. You only need to use it when you're casting to a derived class. This is exclusively to be used in inheritence when you cast from base class to derived class.

Is Static_cast faster than dynamic_cast?

While typeid + static_cast is faster than dynamic_cast , not having to switch on the runtime type of the object is faster than any of them. Save this answer.

What is the use of dynamic_cast operator in C++?

The primary purpose for the dynamic_cast operator is to perform type-safe downcasts. A downcast is the conversion of a pointer or reference to a class A to a pointer or reference to a class B , where class A is a base class of B .

Can dynamic_cast throw exception?

dynamic_cast will no longer throw an exception when type-id is an interior pointer to a value type, with the cast failing at runtime. The cast will now return the 0 pointer value instead of throwing.


2 Answers

Under C++11, instead of doing all this bind stuff, I would use a lambda:

for_each (vec.begin(), vec.end(), [] (C1* c1) 
{
  C2* c2 = dynamic_cast <C2*> (c1);
  if (c2)
  { 
    c2->f();
  }
});

If using C++11 isn't possible, or if for some other reason you shy away from this, then I would construct a functor to wrap this in:

struct call_f
:
  public std::unary_function <C1*, void>
{
  void operator () (C1* c1) const
  {
    C2* c2 = dynamic_cast <C2*> (c1);
    if (c2)
    {
      c2->f();
    }
  }
};

// ...

for_each (vec.begin(), vec.end(), call_f());
like image 123
John Dibling Avatar answered Oct 16 '22 07:10

John Dibling


dynamic_cast<...>() may look like a function but it isn't one. You could use something like this:

template <typename T>
struct dynamic_cast_fun {
    template <typename F>
    T* operator()(F* from) const {
        return dynamic_cast<T*>(F* from);
    }
};

(possibly with some extra overloads to deal with the constness of the argument).

like image 44
Dietmar Kühl Avatar answered Oct 16 '22 07:10

Dietmar Kühl