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_castor throughhelperclass) 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
Post a Comment