Can I tell which template instance class(es) my cl

2019-05-10 02:38发布

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

1条回答
\"骚年 ilove
2楼-- · 2019-05-10 03:13

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.

查看更多
登录 后发表回答