Given this code:
template < int I >
class Foo
{
public:
int v;
Foo() { v = I; }
virtual ~Foo() {}
};
class Bar : public Foo<0>, public Foo<3>
{
public:
template < int I >
int getValue() { return Foo<I>::v; }
};
int main() {
Bar b;
cout << b.getValue<0>() << endl; // prints 0
cout << b.getValue<3>() << endl; // prints 3
cout << b.getValue<4>() << endl; // compiler error
return 0;
}
Is it possible to iterate over all Foo<i>
classes from which Bar
inherits? We can assume that i
is between 0 and some maximum N
. In pseudocode:
for ( int i = 0; i < N; i++ )
{
if ( Bar inherits from `Foo<i>` )
{
cout << Foo<i>::v << endl;
}
}
Here you go (live example):
struct _do { template <typename... A> _do(A&&...) { } };
template <int... I>
class Bar_impl : public Foo<I>...
{
public:
template < int K >
int getValue() { return Foo<K>::v; }
template <typename F>
void loop(F&& f) { _do{(std::forward<F>(f)(getValue<I>()), 0)...}; }
};
using Bar = Bar_impl<0,3>;
Now Bar
implementation holds all indices of base classes in variadic parameter I...
and derives all base classes Foo<I>...
in a variadic fashion.
Function loop
iterates over all bases using the auxiliary struct
_do
. You can pass an arbitrary function, lambda or function object f
to loop
. Then f
will be called on getValue<I>()
for all I...
, i.e., on member v
of every base class.
You use this as follows:
void print(int i) { cout << i << " "; }
int main() {
Bar b;
b.loop(print); // prints 0 3
cout << endl;
}
In other words, you don't need to detect if an object is an instance of some class. You make the object know its own bases by construction.
Now you may realize that if you make Foo
a template on the member type (instead of int
), you are quite close to start building your own very basic tuple.