Assume I have a virtual base class and some derived concrete classes:
class Base { ... }
class DerivedA : public Base { ... }
class DerivedB : public Base { ... }
class DerivedC : public Base { ... }
And somewhere I have vectors of objects of each derived class:
std::vector<DerivedA> my_a;
std::vector<DerivedB> my_b;
std::vector<DerivedC> my_c;
Now, quite often I need to iterate over all elements in all three vectors and exercise the base class interface. I could write three for-loops, doing exactly the same in each. But obviously that's a far from optimal solution.
Is there a clever way to concatenate the vectors into a common container with base-class pointers/references, such that I need to iterate only once? Or any other idea how to solve this elegantly?
There's no need for polymorphism in your current situation. You could simply use a variadic template + higher-order function to iterate over the vectors. Here's a C++17 solution using a fold expression:
template <typename F, typename... Vectors>
void for_all_vectors(F&& f, Vectors&&... vs)
{
(std::for_each(std::forward<Vectors>(vs).begin(),
std::forward<Vectors>(vs).end(),
f), ...);
}
Usage:
int main()
{
std::vector<A> my_a;
std::vector<B> my_b;
std::vector<C> my_c;
for_all_vectors([](const auto& x){ something(x); }, my_a, my_b, my_c);
}
live example on wandbox
In C++11/14 you can replace the fold expression with for_each_argument
:
template <typename TF, typename... Ts>
void for_each_argument(TF&& f, Ts&&... xs)
{
return (void)std::initializer_list<int>{
(f(std::forward<Ts>(xs)), 0)...};
}
template <typename F, typename... Vectors>
void for_all_vectors(F&& f, Vectors&&... vs)
{
for_each_argument([&f](auto&& v)
{
std::for_each(v.begin(), v.end(), f);
}, std::forward<Vectors>(vs)...);
}
live example on wandbox
I explain the idea behind this snippet and expand upon it in this CppCon 2015 talk: "for_each_argument
explained and expanded".
Just have a pointer to the base class. You can't have a vector of type base and put derived classes into it because they might not be the same size, same functions, ect.
So what I would do is create a vector or type base* and then you can concatenate the pointers of the derived class.
Probably would look something like:
vector<base*> v;
v.push_back(&derivedClassVariableA);
v.push_back(&derivedClassVariableB);
Then as long as the functions you are looking to use are virtual in the base and are defined in the derived, you should be good to go
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With