#include <iostream>
using namespace std;
class Base {
public:
virtual void func1() {}
virtual void func2() {}
virtual void func3() {}
virtual ~Base() {}
};
template<class B> class Derived1 : public B {
public:
void func1() {
cout << "Derived1" << endl;
B::func1();
}
};
template<class B> class Derived2 : public B {
public:
void func2() {
cout << "Derived2" << endl;
B::func2();
}
};
template<class B> class Derived3 : public B {
public:
void func3() {
cout << "Derived3" << endl;
B::func3();
}
};
int main() {
typedef Derived1<Derived2<Base>> Foo;
Base *foo = new Foo;
foo->func1();
foo->func2();
foo->func3(); // do nothing
cout << "---------\n";
typedef Derived2<Derived3<Base>> Qoo;
Base *qoo = new Qoo;
qoo->func1(); // do nothing
qoo->func2();
qoo->func3();
cout << "---------\n";
typedef Derived1<Derived1<Base>> Hoo;
Base *hoo = new Hoo;
hoo->func1(); // output twice
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCmNsYXNzIEJhc2UgewpwdWJsaWM6CiAgICB2aXJ0dWFsIHZvaWQgZnVuYzEoKSB7fQogICAgdmlydHVhbCB2b2lkIGZ1bmMyKCkge30KICAgIHZpcnR1YWwgdm9pZCBmdW5jMygpIHt9CiAgICB2aXJ0dWFsIH5CYXNlKCkge30KfTsKCnRlbXBsYXRlPGNsYXNzIEI+IGNsYXNzIERlcml2ZWQxIDogcHVibGljIEIgewpwdWJsaWM6CiAgICB2b2lkIGZ1bmMxKCkgewogICAgICAgIGNvdXQgPDwgIkRlcml2ZWQxIiA8PCBlbmRsOwogICAgICAgIEI6OmZ1bmMxKCk7CiAgICB9Cn07Cgp0ZW1wbGF0ZTxjbGFzcyBCPiBjbGFzcyBEZXJpdmVkMiA6IHB1YmxpYyBCIHsKcHVibGljOgogICAgdm9pZCBmdW5jMigpIHsKICAgICAgICBjb3V0IDw8ICJEZXJpdmVkMiIgPDwgZW5kbDsKICAgICAgICBCOjpmdW5jMigpOwogICAgfQp9OwoKdGVtcGxhdGU8Y2xhc3MgQj4gY2xhc3MgRGVyaXZlZDMgOiBwdWJsaWMgQiB7CnB1YmxpYzoKICAgIHZvaWQgZnVuYzMoKSB7CiAgICAgICAgY291dCA8PCAiRGVyaXZlZDMiIDw8IGVuZGw7CiAgICAgICAgQjo6ZnVuYzMoKTsKICAgIH0KfTsKCmludCBtYWluKCkgewogICAgdHlwZWRlZiBEZXJpdmVkMTxEZXJpdmVkMjxCYXNlPj4gRm9vOwogICAgQmFzZSAqZm9vID0gbmV3IEZvbzsKICAgIGZvby0+ZnVuYzEoKTsKICAgIGZvby0+ZnVuYzIoKTsKICAgIGZvby0+ZnVuYzMoKTsgIC8vIGRvIG5vdGhpbmcKICAgIGNvdXQgPDwgIi0tLS0tLS0tLVxuIjsKICAgIHR5cGVkZWYgRGVyaXZlZDI8RGVyaXZlZDM8QmFzZT4+IFFvbzsKICAgIEJhc2UgKnFvbyA9IG5ldyBRb287CiAgICBxb28tPmZ1bmMxKCk7ICAvLyBkbyBub3RoaW5nCiAgICBxb28tPmZ1bmMyKCk7CiAgICBxb28tPmZ1bmMzKCk7CiAgICBjb3V0IDw8ICItLS0tLS0tLS1cbiI7CiAgICB0eXBlZGVmIERlcml2ZWQxPERlcml2ZWQxPEJhc2U+PiBIb287CiAgICBCYXNlICpob28gPSBuZXcgSG9vOwogICAgaG9vLT5mdW5jMSgpOyAgLy8gb3V0cHV0IHR3aWNlCn0K