Iterating over different types
Solution 1:
In C++17 or better you'd use fold expressions, to "walk through" your heterogenous arguments applying the member function:
auto Printer = [](auto&&... args) {
(args.show(), ...);
};
Printer(w1, w2, w3, w4, w5, w6, t1, t2, t3);
Demo
You can read more on this in my blog
Solution 2:
boost::fusion is awesome but oldskool - it caters for the deficiencies in c++03.
c++11's variadic template expansion to the rescue!
#include <iostream>
struct Window{
void show() {
std::cout << "Window\n";
}
//stuff
}w1, w2, w3;
struct Widget{
void show() {
std::cout << "Widget\n";
}
//stuff
}w4, w5, w6;
struct Toolbar{
void show()
{
std::cout << "Toolbar\n";
}
//stuff
}t1, t2, t3;
template<class...Objects>
void call_show(Objects&&...objects)
{
using expand = int[];
(void) expand { 0, ((void)objects.show(), 0)... };
}
auto main() -> int
{
call_show(w3, w4, w5, t1);
return 0;
}
expected output:
Window
Widget
Widget
Toolbar
another, more generic way (requires c++14):
// note that i have avoided a function names that look like
// one in the standard library.
template<class Functor, class...Objects>
void for_all(Functor&& f, Objects&&... objects)
{
using expand = int[];
(void) expand { 0, (f(std::forward<Objects>(objects)), 0)... };
}
called like so:
for_all([](auto& thing) { thing.show(); }, w3, w4, w5, t1);
Solution 3:
Another option is to use boost::tuple
or std::tuple
and boost::fusion::for_each
algorithm:
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/adapted/boost_tuple.hpp>
boost::fusion::for_each(
boost::tie(w1, w2, w3, w4, w5, w6, t1, t2, t3), // by reference, not a copy
[](auto&& t) { t.show(); }
);
Just out of curiosity, compared the generated assembly output of Richard Hodges's method with the above. With gcc-4.9.2 -Wall -Wextra -std=gnu++14 -O3 -march=native
the produced assembly code is identical.