Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I cast std::vector<Animal*> to std::vector<Dog*> without looking at each element?

I have a base class with several classes extending it. I have some generic library utilities that creates a vector containing pointers to the base class so that any of the subclasses will work. How can I cast all of the elements of the vector to a specific child class?

// A method is called that assumes that a vector containing
// Dogs casted to Animal is passed.
void myDogCallback(vector<Animal*> &animals) {
    // I want to cast all of the elements of animals to
    // be dogs.
    vector<Dog*> dogs = castAsDogs(animals);
}

My naive solution would look something like this:

// A method is called that assumes that a vector containing
// Dogs casted to Animal is passed.
void myDogCallback(vector<Animal*> &animals) {
    // I want to cast all of the elements of animals to
    // be dogs.
    vector<Dog*> dogs;
    vector<Animal*>::iterator iter;
    for ( iter = animals.begin(); iter != animals.end(); ++iter ) {
        dogs.push_back(dynamic_cast<Dog*>(*iter));
    }
}
like image 642
Beau Simensen Avatar asked Jul 24 '09 03:07

Beau Simensen


People also ask

How do you create a vector from another vector in C++?

The simplest way to create a vector from another vector is to use the assignment operator ( = ). vector<int> v2; v2 = v1; The code initializes a vector v2. Then we use the assignment operator to copy all elements of vector v1 to v2.

Is vector guaranteed to be contiguous?

Yes, the elements of a std::vector are guaranteed to be contiguous.

Can you use a vector as a queue?

You "can" use a vector over a queue, if the queue lifetime is short or if you know the maximum size of your queue.

How do you check if something is present in a std vector?

The most straightforward solution is to count the total number of elements in the vector that have the specified value. If the count is greater than zero, we've found our element. This is simple to accomplish with the std::count function.


1 Answers

You could use std::transform. It still uses for() internally, but you'll get two-string implementation:

#include <vector>
#include <algorithm>
using namespace std;

struct Animal { virtual ~Animal() {} };
struct Dog : Animal { virtual ~Dog() {} };

template<typename Target>
struct Animal2Target { Target* operator ()( Animal* value ) const { return dynamic_cast<Target*>(value); } };

void myDogCallback(vector<Animal*> &animals) {
{
    vector<Dog*> dogs;
    transform( animals.begin(), animals.end(), dogs.begin(), Animal2Target<Dog>() );
}
like image 135
Kirill V. Lyadvinsky Avatar answered Oct 02 '22 20:10

Kirill V. Lyadvinsky