#include <iostream>
#include <unordered_map>
#include <typeindex>
#include <functional>
using namespace std;
struct Container {
template <class I, class C>
void assoc() {
generators[typeid(I)] = []() -> C * { return new C; };
}
template <class I>
I * get() {
auto g = generators[typeid(I)];
return g ? static_cast<I *>(g()) : 0;
}
unordered_map<type_index, function<void *(void)>> generators;
};
struct IVehicle {
virtual void sayHello() = 0;
};
struct Car : IVehicle {
void sayHello() override { cout << "Hello, I am a Car!" << endl; }
};
struct Bicycle : IVehicle {
void sayHello() override { cout << "Hello, I am a Bicycle!" << endl; }
};
void test(Container & c) {
auto v = c.get<IVehicle>();
if (v) {
v->sayHello();
} else {
cout << "Couldn't find vehicle :(" << endl;
}
}
int main() {
Container c;
test(c);
c.assoc<IVehicle, Car>();
test(c);
c.assoc<IVehicle, Bicycle>();
test(c);
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dW5vcmRlcmVkX21hcD4KI2luY2x1ZGUgPHR5cGVpbmRleD4KI2luY2x1ZGUgPGZ1bmN0aW9uYWw+Cgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKc3RydWN0IENvbnRhaW5lciB7CgogICAgdGVtcGxhdGUgPGNsYXNzIEksIGNsYXNzIEM+CiAgICB2b2lkIGFzc29jKCkgewogICAgICAgIGdlbmVyYXRvcnNbdHlwZWlkKEkpXSA9IFtdKCkgLT4gQyAqIHsgcmV0dXJuIG5ldyBDOyB9OwogICAgfQoKICAgIHRlbXBsYXRlIDxjbGFzcyBJPgogICAgSSAqIGdldCgpIHsKICAgICAgICBhdXRvIGcgPSBnZW5lcmF0b3JzW3R5cGVpZChJKV07CiAgICAgICAgcmV0dXJuIGcgPyBzdGF0aWNfY2FzdDxJICo+KGcoKSkgOiAwOwogICAgfQoKICAgIHVub3JkZXJlZF9tYXA8dHlwZV9pbmRleCwgZnVuY3Rpb248dm9pZCAqKHZvaWQpPj4gZ2VuZXJhdG9yczsKfTsKCnN0cnVjdCBJVmVoaWNsZSB7CiAgICB2aXJ0dWFsIHZvaWQgc2F5SGVsbG8oKSA9IDA7Cn07CgpzdHJ1Y3QgQ2FyIDogSVZlaGljbGUgewogICAgdm9pZCBzYXlIZWxsbygpIG92ZXJyaWRlIHsgY291dCA8PCAiSGVsbG8sIEkgYW0gYSBDYXIhIiA8PCBlbmRsOyB9Cn07CgpzdHJ1Y3QgQmljeWNsZSA6IElWZWhpY2xlIHsKICAgIHZvaWQgc2F5SGVsbG8oKSBvdmVycmlkZSB7IGNvdXQgPDwgIkhlbGxvLCBJIGFtIGEgQmljeWNsZSEiIDw8IGVuZGw7IH0KfTsKCnZvaWQgdGVzdChDb250YWluZXIgJiBjKSB7CgogICAgYXV0byB2ID0gYy5nZXQ8SVZlaGljbGU+KCk7CgogICAgaWYgKHYpIHsKICAgICAgICB2LT5zYXlIZWxsbygpOwogICAgfSBlbHNlIHsKICAgICAgICBjb3V0IDw8ICJDb3VsZG4ndCBmaW5kIHZlaGljbGUgOigiIDw8IGVuZGw7CiAgICB9Cgp9CgppbnQgbWFpbigpIHsKCiAgICBDb250YWluZXIgYzsKCiAgICB0ZXN0KGMpOwoKICAgIGMuYXNzb2M8SVZlaGljbGUsIENhcj4oKTsKICAgIHRlc3QoYyk7CgogICAgYy5hc3NvYzxJVmVoaWNsZSwgQmljeWNsZT4oKTsKICAgIHRlc3QoYyk7Cgp9