可变参数模板的多重继承:如何为每个基类调用函数?
我有一个钻石继承计划,其中最后一个孩子应该能够从许多不同的父母那里继承。
I have a diamond inheritance scheme, where the last child should be able to inherit from many different parents.
A
/|\
/ | \
B C ...
| | |
* *
D E
现在想象我有一个 D类:公共B
, E类:公共B,公共C
,等等。来自 D
我想调用其所有父对象的相同函数,由于继承,我保证该函数存在。我的想法是我可以将其包装在可变参数的模板中。
Now imagine I have a class D : public B
, class E : public B, public C
, etc. From D
I want to call the same function of all its parents, which I am guaranteed exists due to the inheritance. My thought was that I could wrap this in some variadic template.
当前,我有以下内容:
template <typename T>
class A
{
public:
A(T t) : mT(t) {}
virtual ~A() {}
virtual void doThings() = 0;
protected:
T mT;
};
template <typename T, typename A = A<T>>
class B : public A
{
public:
B(T t) : A(t) {}
virtual ~B() {}
virtual void doThings() { std::cout << "B" << std::endl; }
};
template <typename T, typename A = A<T>>
class C : public A
{
public:
C(T t) : A(t) {}
virtual ~C() {}
virtual void doThings() { std::cout << "C" << std::endl; }
};
现在我想我可以做这样的事情,但显然不起作用:
Now I thought I could do something like this, which obviously does not work:
template <typename T, typename ...Args>
class ChildGenerator : public Args...
{
public:
ChildGenerator(T t) : Args(t)... {}
// The unpacking of the variadic template does not work here.
// Do I need to make it recursive somehow? How can I do that without having to instantiate new classes B and C?
void doThings() override { Args...::doThings();}
};
我希望我可以这样使用它:
My hope is that I can use it like so:
int main()
{
using B = B<double>;
using C = C<double>;
B c1(0.0);
C c2(1.0);
ChildGenerator<double, B, C> c3(2.0);
c1.doThings();
c2.doThings();
c3.doThings();
}
预期产量(顺序无关紧要):
Expected output (order does not matter):
B
C
B // <-- order of these two does not matter
C // <--
我要实现的目标是可能的吗?
Is what I'm trying to achieve possible?
一种迭代可变参数基数的方法:
One way to iterate over the variadic bases:
template <typename T, typename ...Args>
class ChildGenerator : public Args...
{
public:
ChildGenerator(T t) : Args(t)... {}
void doThings() override {
int dummy[] = {0, (Args::doThings(), void(), 0)...};
static_cast<void>(dummy); // avoid warning for unused variable
}
};
或在C ++ 17中,带有折叠表达式:
or in C++17, with folding expression:
void doThings() override {
(static_cast<void>(Args::doThings()), ...);
}