我可以告诉我的类继承哪个模板实例类吗?

时间:2014-04-05 14:54:03

标签: c++ templates inheritance reflection multiple-inheritance

鉴于此代码:

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;
    }
}

1 个答案:

答案 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