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