#include <iostream>
#include <type_traits>
class SubType {};
class A : SubType {
// things
};
class B : public A {
// more things
};
class SubBase {
/* default impl. */
public:
virtual A* get() = 0;
};
template <typename T>
class Base : public SubBase {
public:
Base(SubType* subinst) :instance((void*)subinst) {}
Base(void* inst) :instance(inst) {}
Base(T* t) :Base(dynamic_cast<A*>(t)) {}
public:
void* instance;
};
template <typename T, typename = typename std::is_base_of<T, A>::type>
class Wrapper : public Base<T> {
public:
Wrapper(T* t) :Base<T>(static_cast<void*>(t)) {}
virtual T* get() { return (T*)Base<T>::instance; }
};
class Worker {
public:
void work(Wrapper<A>* wa){
A* a = wa->get();
//do stuff with a.
}
};
int main() {
B b;
Worker worker;
Wrapper<B> wrapped_b(&b);
worker.work((Wrapper<A>*)&wrapped_b);
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CgpjbGFzcyBTdWJUeXBlIHt9OwoKY2xhc3MgQSA6IFN1YlR5cGUgewogIC8vIHRoaW5ncwp9OwoKY2xhc3MgQiA6IHB1YmxpYyBBIHsKICAvLyBtb3JlIHRoaW5ncwp9OwoKY2xhc3MgU3ViQmFzZSB7CgkvKiBkZWZhdWx0IGltcGwuICovCglwdWJsaWM6CgkgICAgdmlydHVhbCBBKiBnZXQoKSA9IDA7Cgp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CmNsYXNzIEJhc2UgOiBwdWJsaWMgU3ViQmFzZSB7CglwdWJsaWM6CgkJQmFzZShTdWJUeXBlKiBzdWJpbnN0KSA6aW5zdGFuY2UoKHZvaWQqKXN1Ymluc3QpIHt9CgkJQmFzZSh2b2lkKiBpbnN0KSA6aW5zdGFuY2UoaW5zdCkge30KCQlCYXNlKFQqIHQpIDpCYXNlKGR5bmFtaWNfY2FzdDxBKj4odCkpIHt9CglwdWJsaWM6CgkJdm9pZCogaW5zdGFuY2U7Cgp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lID0gdHlwZW5hbWUgc3RkOjppc19iYXNlX29mPFQsIEE+Ojp0eXBlPgpjbGFzcyBXcmFwcGVyIDogcHVibGljIEJhc2U8VD4gewoJcHVibGljOgoJCVdyYXBwZXIoVCogdCkgOkJhc2U8VD4oc3RhdGljX2Nhc3Q8dm9pZCo+KHQpKSB7fQoJICAgIHZpcnR1YWwgVCogZ2V0KCkgeyByZXR1cm4gKFQqKUJhc2U8VD46Omluc3RhbmNlOyB9Cn07CgpjbGFzcyBXb3JrZXIgewoJcHVibGljOgoJICB2b2lkIHdvcmsoV3JhcHBlcjxBPiogd2EpewogICAgCUEqIGEgPSB3YS0+Z2V0KCk7CiAgICAJLy9kbyBzdHVmZiB3aXRoIGEuCiAgCSAgfQp9OwoKaW50IG1haW4oKSB7CglCIGI7CglXb3JrZXIgd29ya2VyOwoJV3JhcHBlcjxCPiB3cmFwcGVkX2IoJmIpOwoJd29ya2VyLndvcmsoKFdyYXBwZXI8QT4qKSZ3cmFwcGVkX2IpOwp9