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 throughhelper
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
Post a Comment