#include <iostream>
#include <string>
#include <typeinfo>
#include <unordered_map>
#include <functional>
#include <typeindex>
#include <cassert>
class Renderer;
struct Renderable { virtual ~Renderable() {} };
struct SelfRenderable : Renderable {
virtual void Render(Renderer& render) = 0;
};
class Renderer {
public:
std::unordered_map<std::type_index, std::function<void(Renderer& renderer, const Renderable& renderable)>> rendering_functions;
void Render(Renderable& renderable) {
if (rendering_functions.find(typeid(renderable)) != rendering_functions.end())
return rendering_functions[typeid(renderable)](*this, renderable);
if (auto self = dynamic_cast<SelfRenderable*>(&renderable))
return self->Render(*this);
assert(false);
}
template<typename T, typename F> void AddRenderingFunction(F f) {
rendering_functions[typeid(T)] = [f](Renderer& renderer, const Renderable& renderable) {
return f(renderer, static_cast<const T&>(renderable));
};
}
void RenderText(std::string text) {
std::cout << text;
}
};
struct Player : Renderable {
std::string name;
};
int main() {
Renderer r;
Player p;
p.name = "Hello, World!";
r.AddRenderingFunction<Player>([](Renderer& rend, const Player& p) {
rend.RenderText(p.name);
});
r.Render(p);
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8dHlwZWluZm8+CiNpbmNsdWRlIDx1bm9yZGVyZWRfbWFwPgojaW5jbHVkZSA8ZnVuY3Rpb25hbD4KI2luY2x1ZGUgPHR5cGVpbmRleD4KI2luY2x1ZGUgPGNhc3NlcnQ+CgpjbGFzcyBSZW5kZXJlcjsKc3RydWN0IFJlbmRlcmFibGUgeyB2aXJ0dWFsIH5SZW5kZXJhYmxlKCkge30gfTsKc3RydWN0IFNlbGZSZW5kZXJhYmxlIDogUmVuZGVyYWJsZSB7CiAgICB2aXJ0dWFsIHZvaWQgUmVuZGVyKFJlbmRlcmVyJiByZW5kZXIpID0gMDsKfTsKY2xhc3MgUmVuZGVyZXIgewpwdWJsaWM6CiAgICBzdGQ6OnVub3JkZXJlZF9tYXA8c3RkOjp0eXBlX2luZGV4LCBzdGQ6OmZ1bmN0aW9uPHZvaWQoUmVuZGVyZXImIHJlbmRlcmVyLCBjb25zdCBSZW5kZXJhYmxlJiByZW5kZXJhYmxlKT4+IHJlbmRlcmluZ19mdW5jdGlvbnM7CiAgICB2b2lkIFJlbmRlcihSZW5kZXJhYmxlJiByZW5kZXJhYmxlKSB7CiAgICAgICAgaWYgKHJlbmRlcmluZ19mdW5jdGlvbnMuZmluZCh0eXBlaWQocmVuZGVyYWJsZSkpICE9IHJlbmRlcmluZ19mdW5jdGlvbnMuZW5kKCkpCiAgICAgICAgICAgIHJldHVybiByZW5kZXJpbmdfZnVuY3Rpb25zW3R5cGVpZChyZW5kZXJhYmxlKV0oKnRoaXMsIHJlbmRlcmFibGUpOwogICAgICAgIGlmIChhdXRvIHNlbGYgPSBkeW5hbWljX2Nhc3Q8U2VsZlJlbmRlcmFibGUqPigmcmVuZGVyYWJsZSkpCiAgICAgICAgICAgIHJldHVybiBzZWxmLT5SZW5kZXIoKnRoaXMpOwogICAgICAgIGFzc2VydChmYWxzZSk7CiAgICB9CiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBULCB0eXBlbmFtZSBGPiB2b2lkIEFkZFJlbmRlcmluZ0Z1bmN0aW9uKEYgZikgewogICAgICAgIHJlbmRlcmluZ19mdW5jdGlvbnNbdHlwZWlkKFQpXSA9IFtmXShSZW5kZXJlciYgcmVuZGVyZXIsIGNvbnN0IFJlbmRlcmFibGUmIHJlbmRlcmFibGUpIHsKICAgICAgICAgICAgcmV0dXJuIGYocmVuZGVyZXIsIHN0YXRpY19jYXN0PGNvbnN0IFQmPihyZW5kZXJhYmxlKSk7CiAgICAgICAgfTsKICAgIH0KICAgIHZvaWQgUmVuZGVyVGV4dChzdGQ6OnN0cmluZyB0ZXh0KSB7IAogICAgCXN0ZDo6Y291dCA8PCB0ZXh0OwogICAgfQp9OwpzdHJ1Y3QgUGxheWVyIDogUmVuZGVyYWJsZSB7CiAgICBzdGQ6OnN0cmluZyBuYW1lOwp9OwppbnQgbWFpbigpIHsKICAgIFJlbmRlcmVyIHI7CiAgICBQbGF5ZXIgcDsKICAgIHAubmFtZSA9ICJIZWxsbywgV29ybGQhIjsKICAgIHIuQWRkUmVuZGVyaW5nRnVuY3Rpb248UGxheWVyPihbXShSZW5kZXJlciYgcmVuZCwgY29uc3QgUGxheWVyJiBwKSB7CiAgICAgICAgcmVuZC5SZW5kZXJUZXh0KHAubmFtZSk7CiAgICB9KTsKICAgIHIuUmVuZGVyKHApOwp9