Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ std::copy with type cast to derived class possible?

I am pretty sure that there is no way around doing this explicitly but I would like to ask nontheless in case there is a better way. I have a base class A and a derived class B, now I have a std::list of A* which point to B*'s and I want to copy this list of A*'s to a std::vector of B*'s so basically I want to do this:

std::list<A*> aList = someObject.getAs();
std::vector<B*> bVec = std::vector<B*>(aList.begin(), aList.end());

I am pretty sure this should compile when the list and the vector would be the same type (eg both were A*'s), but since in this case A* is the base class of B* I can't do it this way, because I would have to explicitly typecast for instance like this:

std::list<A*> aList = someObject.getAs();
std::vector<B*> bVec;
bVec.reserve(aList.size());
std::list<A*>::iterator it = aList.begin();
for(it; it!=aList.end(); ++it)
{
   B* b = static_cast<B*>(*it);
   bVec.push_back(b);
}

Is there any more elegant way than my second approach or will I have to do it like that?

like image 386
moka Avatar asked Aug 18 '10 15:08

moka


1 Answers

It's not safe do the conversion implicitly, so you have to make it explicit. The standard algorithm for applying some kind of transformation to a sequence is std::transform, which you can use to populate an empty container as follows:

struct A {};
struct B : A {};

template <typename From, typename To>
struct static_caster
{
    To* operator()(From* p) {return static_cast<To*>(p);}
};

std::list<A*> a;
std::vector<B*> b;
std::transform(a.begin(), a.end(), std::back_inserter(b), static_caster<A,B>());
like image 62
Mike Seymour Avatar answered Sep 28 '22 18:09

Mike Seymour