c++ - C++11 range-based for loop on derived objects -


if have vector of pointers parent class, , vector initialized instantiating objects derived parent class, appears can't use range-based loop obtain elements derived objects. here's simple example:

#include <vector>  class parent {}; class derived : public parent {};  int main() {     std::vector<parent*> objects { new derived(), new derived() };      (derived* d : objects) {    // error         // use d     }      return 0; } 

is there clean way want (i.e., loop through derived objects)? know can this:

for (parent* p : objects) {     derived* d = static_cast<derived*>(p);     // use d } 

but cleanest way c++11? other alternatives?

the cppreference.com page states range-based loop expression produces code similar following (__range, __begin , __end exposition only):

for ( range_declaration : range_expression ) loop_statement

{     auto && __range = range_expression ;      (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) {          range_declaration = *__begin;          loop_statement      }  } 

with description, deduce __begin , __end must of same type, in fact, isn't case. pointer parent isn't pointer derived, must casted explicitly , range-based loop not perform cast @ all.

in order achieve you're looking for, create helper class performs cast me1, example:

struct helper {     helper(parent *p) : obj(p) {}     parent *const obj;     operator derived *() { return static_cast<derived *>(obj); } }; 

this helper allows following:

std::vector<parent*> objects { new derived(), new derived() };  (helper h : objects) {     derived *d = h;     d->use(); } 

we can templatize helper class in order use on other parent-derived contexts:

template <typename t> struct thelper {     thelper(parent *p) : obj(p) {}     parent *const obj;     operator t *() { return static_cast<t *>(obj); } };  ... ...  (thelper<derived> h : objects) {     derived *d = h;     d->use(); }  (thelper<derived2> h : objects) {     derived *d = h;     d->use(); } 

but if objects vector contains mixed types, dangerous.

as improvement, can replace static_cast dynamic_cast , check nullptr, must aware of it's overhead.

this isn't solution use on project of mine hope looks clean , neat ;)

edit

however, conversion (whether explicit static_cast or through helper class) still required additional line inside loop.

as talked before, cast (static or dynamic) mandatory, if you're concerned neatness of loop being truncated addition of additional line, overloading operator -> should trick:

struct helper {     helper(parent *p) : obj(p) {}     parent *const obj;     operator derived *() { return static_cast<derived *>(obj); }     derived *operator ->() { return static_cast<derived *>(obj); } };  (helper h : objects) {     h->use(); } 

note if you're using operator -> cannot check nullptr, necessary if objects vector have mixed derived types.

i've updated live demoin order include new code.


1 although, can read on comments, there better ways achieve goal.


Comments

Popular posts from this blog

javascript - Jquery show_hide, what to add in order to make the page scroll to the bottom of the hidden field once button is clicked -

python - Django-cities exits with "killed" -

python - How to get a widget position inside it's layout in Kivy? -