鉴于此代码:
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;
}
是否可以迭代Foo<i>
继承的所有Bar
类?我们可以假设i
介于0和最大N
之间。在伪代码中:
for ( int i = 0; i < N; i++ )
{
if ( Bar inherits from `Foo<i>` )
{
cout << Foo<i>::v << endl;
}
}
答案 0 :(得分:4)
你去(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>;
现在Bar
实现包含variadic参数I...
中所有基类的索引,并以可变方式派生所有基类Foo<I>...
。
函数loop
使用辅助struct
_do
遍历所有基础。您可以将任意函数lambda或函数对象f
传递给loop
。然后,f
将针对所有getValue<I>()
,即每个基类的成员I...
调用v
。
您可以按如下方式使用:
void print(int i) { cout << i << " "; }
int main() {
Bar b;
b.loop(print); // prints 0 3
cout << endl;
}
换句话说,如果对象是某个类的实例,则不需要检测。您可以通过构造使对象知道自己的基础。
现在您可能会意识到,如果您在成员类型(而不是Foo
)上设置int
模板,那么您就可以开始构建自己的very basic tuple。