#include <vector>
#include <type_traits>
struct Parent { };
struct A : Parent { };
struct B : Parent { };
struct C : Parent { };
struct E : Parent { };
struct tag_none { };
struct tag_A { };
struct tag_B { };
struct tag_C { };
template <typename T>
struct component_tag { using type = tag_none; };
template <>
struct component_tag <A> { using type = tag_A; };
template <>
struct component_tag <B> { using type = tag_B; };
template <>
struct component_tag <C> { using type = tag_C; };
class D
{
public:
template <typename T>
void Store();
private:
void Store_impl(void*, tag_none);
void Store_impl(A* component, tag_A);
void Store_impl(B* component, tag_B);
void Store_impl(C* component, tag_C);
A *mA;
B *mB;
C *mC;
std::vector<Parent*> mComponents;
};
template <typename T>
void D::Store()
{
using originalType = std::decay_t<std::remove_pointer_t<T> >;
originalType* component = new originalType();
Store_impl(component, typename component_tag<originalType>::type { });
mComponents.push_back(component);
}
void D::Store_impl(void*, tag_none)
{
// do nothing
}
void D::Store_impl(A* component, tag_A)
{
mA = component;
}
void D::Store_impl(B* component, tag_B)
{
mB = component;
}
void D::Store_impl(C* component, tag_C)
{
mC = component;
}
int main()
{
A a;
B b;
C c;
E e;
D obj;
obj.Store<A>();
obj.Store<B>();
obj.Store<C>();
obj.Store<E>();
}
I2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPHR5cGVfdHJhaXRzPgoKc3RydWN0IFBhcmVudCB7IH07CnN0cnVjdCBBIDogUGFyZW50IHsgfTsKc3RydWN0IEIgOiBQYXJlbnQgeyB9OwpzdHJ1Y3QgQyA6IFBhcmVudCB7IH07CnN0cnVjdCBFIDogUGFyZW50IHsgfTsKCnN0cnVjdCB0YWdfbm9uZSB7IH07CnN0cnVjdCB0YWdfQSB7IH07CnN0cnVjdCB0YWdfQiB7IH07CnN0cnVjdCB0YWdfQyB7IH07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IGNvbXBvbmVudF90YWcgeyB1c2luZyB0eXBlID0gdGFnX25vbmU7IH07CnRlbXBsYXRlIDw+CnN0cnVjdCBjb21wb25lbnRfdGFnIDxBPiB7IHVzaW5nIHR5cGUgPSB0YWdfQTsgfTsKdGVtcGxhdGUgPD4Kc3RydWN0IGNvbXBvbmVudF90YWcgPEI+IHsgdXNpbmcgdHlwZSA9IHRhZ19COyB9Owp0ZW1wbGF0ZSA8PgpzdHJ1Y3QgY29tcG9uZW50X3RhZyA8Qz4geyB1c2luZyB0eXBlID0gdGFnX0M7IH07CgpjbGFzcyBECnsKcHVibGljOgogICAgdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CiAgICB2b2lkIFN0b3JlKCk7Cgpwcml2YXRlOgogICAgdm9pZCBTdG9yZV9pbXBsKHZvaWQqLCB0YWdfbm9uZSk7CiAgICB2b2lkIFN0b3JlX2ltcGwoQSogY29tcG9uZW50LCB0YWdfQSk7CiAgICB2b2lkIFN0b3JlX2ltcGwoQiogY29tcG9uZW50LCB0YWdfQik7CiAgICB2b2lkIFN0b3JlX2ltcGwoQyogY29tcG9uZW50LCB0YWdfQyk7CgogICAgQSAqbUE7CiAgICBCICptQjsKICAgIEMgKm1DOwogICAgc3RkOjp2ZWN0b3I8UGFyZW50Kj4gbUNvbXBvbmVudHM7Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kdm9pZCBEOjpTdG9yZSgpCnsKICAgIHVzaW5nIG9yaWdpbmFsVHlwZSA9IHN0ZDo6ZGVjYXlfdDxzdGQ6OnJlbW92ZV9wb2ludGVyX3Q8VD4gPjsKICAgIG9yaWdpbmFsVHlwZSogY29tcG9uZW50ID0gbmV3IG9yaWdpbmFsVHlwZSgpOwoKICAgIFN0b3JlX2ltcGwoY29tcG9uZW50LCB0eXBlbmFtZSBjb21wb25lbnRfdGFnPG9yaWdpbmFsVHlwZT46OnR5cGUgeyB9KTsKCiAgICBtQ29tcG9uZW50cy5wdXNoX2JhY2soY29tcG9uZW50KTsKfQoKdm9pZCBEOjpTdG9yZV9pbXBsKHZvaWQqLCB0YWdfbm9uZSkKewogICAgLy8gZG8gbm90aGluZwp9Cgp2b2lkIEQ6OlN0b3JlX2ltcGwoQSogY29tcG9uZW50LCB0YWdfQSkKewogICAgbUEgPSBjb21wb25lbnQ7Cn0KCnZvaWQgRDo6U3RvcmVfaW1wbChCKiBjb21wb25lbnQsIHRhZ19CKQp7CiAgICBtQiA9IGNvbXBvbmVudDsKfQoKdm9pZCBEOjpTdG9yZV9pbXBsKEMqIGNvbXBvbmVudCwgdGFnX0MpCnsKICAgIG1DID0gY29tcG9uZW50Owp9CgoKaW50IG1haW4oKQp7CglBIGE7CglCIGI7CglDIGM7CglFIGU7CgoJRCBvYmo7CgoJb2JqLlN0b3JlPEE+KCk7CglvYmouU3RvcmU8Qj4oKTsKCW9iai5TdG9yZTxDPigpOwoJCglvYmouU3RvcmU8RT4oKTsKfQ==