#include <functional>
#include <iostream>
#include <stdexcept>
#include <vector>
class C { public: virtual ~C() = default; };
class C0 : public C { public: void print() { std::cout << "C0\n"; } };
class C1 : public C { public: void print() { std::cout << "C1\n"; } };
class PrintCaller
{
public:
template <typename T>
std::size_t register_class()
{
m.push_back([](C* c) {
auto* p = dynamic_cast<T*>(c);
if (p) {
p->print();
} else {
throw std::runtime_error("Incorrect type");
}
});
return m.size() - 1;
}
void print(std::size_t id, C* c) const {
if (id < m.size()) {
m[id](c);
} else {
throw std::runtime_error("invalid id");
}
}
private:
std::vector<std::function<void(C*)>> m;
};
int main()
{
C0 c0;
C1 c1;
PrintCaller p;
std::size_t id1 = p.register_class<C1>();
std::size_t id0 = p.register_class<C0>();
p.print(id0, &c0);
p.print(id1, &c1);
try {
p.print(id1, &c0);
} catch (std::exception& e) {
std::cout << e.what();
}
}
I2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPHN0ZGV4Y2VwdD4KI2luY2x1ZGUgPHZlY3Rvcj4KCmNsYXNzIEMgeyBwdWJsaWM6IHZpcnR1YWwgfkMoKSA9IGRlZmF1bHQ7IH07CmNsYXNzIEMwIDogcHVibGljIEMgeyBwdWJsaWM6IHZvaWQgcHJpbnQoKSB7IHN0ZDo6Y291dCA8PCAiQzBcbiI7IH0gfTsKY2xhc3MgQzEgOiBwdWJsaWMgQyB7IHB1YmxpYzogdm9pZCBwcmludCgpIHsgc3RkOjpjb3V0IDw8ICJDMVxuIjsgfSB9OwoKCmNsYXNzIFByaW50Q2FsbGVyCnsKcHVibGljOgogICAgdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CiAgICBzdGQ6OnNpemVfdCByZWdpc3Rlcl9jbGFzcygpCiAgICB7CiAgICAgICAgbS5wdXNoX2JhY2soW10oQyogYykgewogICAgICAgICAgICBhdXRvKiBwID0gZHluYW1pY19jYXN0PFQqPihjKTsKICAgICAgICAgICAgaWYgKHApIHsKICAgICAgICAgICAgICAgIHAtPnByaW50KCk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICB0aHJvdyBzdGQ6OnJ1bnRpbWVfZXJyb3IoIkluY29ycmVjdCB0eXBlIik7CiAgICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgICByZXR1cm4gbS5zaXplKCkgLSAxOwogICAgfQoKICAgIHZvaWQgcHJpbnQoc3RkOjpzaXplX3QgaWQsIEMqIGMpIGNvbnN0IHsKICAgICAgICBpZiAoaWQgPCBtLnNpemUoKSkgewogICAgICAgICAgICBtW2lkXShjKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0aHJvdyBzdGQ6OnJ1bnRpbWVfZXJyb3IoImludmFsaWQgaWQiKTsKICAgICAgICB9CiAgICB9Cgpwcml2YXRlOgogICAgc3RkOjp2ZWN0b3I8c3RkOjpmdW5jdGlvbjx2b2lkKEMqKT4+IG07Cn07CgoKaW50IG1haW4oKQp7CiAgICBDMCBjMDsKICAgIEMxIGMxOwoKICAgIFByaW50Q2FsbGVyIHA7CgogICAgc3RkOjpzaXplX3QgaWQxID0gcC5yZWdpc3Rlcl9jbGFzczxDMT4oKTsKICAgIHN0ZDo6c2l6ZV90IGlkMCA9IHAucmVnaXN0ZXJfY2xhc3M8QzA+KCk7CgogICAgcC5wcmludChpZDAsICZjMCk7CiAgICBwLnByaW50KGlkMSwgJmMxKTsKICAgIHRyeSB7CiAgICAgICAgcC5wcmludChpZDEsICZjMCk7CiAgICB9IGNhdGNoIChzdGQ6OmV4Y2VwdGlvbiYgZSkgewogICAgICAgIHN0ZDo6Y291dCA8PCBlLndoYXQoKTsKICAgIH0KfQo=