#include <typeindex>
#include <unordered_map>
struct PBase {virtual ~PBase() noexcept = default;};
struct P1 : public PBase {};
struct P2 : public PBase {};
class SBase
{
public:
void doIt(PBase *base)
{
internalDoIt(base);
}
protected:
virtual void internalDoIt(PBase *base) = 0;
};
using callback_type = void(*)(SBase*, PBase*);
using map_type = std::unordered_map<std::type_index, callback_type>;
template <typename P, callback_type Fnc>
struct pair_type {};
template <class ... Pairs>
class BasicS : public SBase
{
protected:
void internalDoIt(PBase *base) override
{
map_[typeid(*base)](this, base);
}
private:
static map_type map_;
};
namespace detail
{
template <class ... Pairs>
struct map_getter;
template <typename P, callback_type F>
struct map_getter<pair_type<P, F>>
{
static map_type get()
{
return map_type{{typeid(P), F}};
}
};
template <typename P, callback_type F, class ... Tail>
struct map_getter<pair_type<P, F>, Tail...>
{
static map_type get()
{
auto m = map_getter<Tail...>::get();
m.emplace(typeid(P), F);
return m;
}
};
}
template <class ... Pairs>
map_type BasicS<Pairs...>::map_ = detail::map_getter<Pairs...>::get();
#include <iostream>
void s1p1DoIt(SBase*, PBase*)
{
std::cout << "S1 P1\n";
}
void s1p2DoIt(SBase*, PBase*)
{
std::cout << "S1 P2\n";
}
class S1 : public BasicS<pair_type<P1, s1p1DoIt>, pair_type<P2, s1p2DoIt>> {};
void s2p1DoIt(SBase*, PBase*)
{
std::cout << "S2 P1\n";
}
void s2p2DoIt(SBase*, PBase*)
{
std::cout << "S2 P2\n";
}
class S2 : public BasicS<pair_type<P1, s2p1DoIt>, pair_type<P2, s2p2DoIt>> {};
int main()
{
S1 s1;
S2 s2;
P1 p1;
P2 p2;
SBase &sbase1 = s1;
SBase &sbase2 = s2;
PBase &pbase1 = p1;
PBase &pbase2 = p2;
sbase1.doIt(&pbase1);
sbase1.doIt(&pbase2);
sbase2.doIt(&pbase1);
sbase2.doIt(&pbase2);
}
I2luY2x1ZGUgPHR5cGVpbmRleD4KI2luY2x1ZGUgPHVub3JkZXJlZF9tYXA+CgpzdHJ1Y3QgUEJhc2Uge3ZpcnR1YWwgflBCYXNlKCkgbm9leGNlcHQgPSBkZWZhdWx0O307CnN0cnVjdCBQMSA6IHB1YmxpYyBQQmFzZSB7fTsKc3RydWN0IFAyIDogcHVibGljIFBCYXNlIHt9OwoKY2xhc3MgU0Jhc2UKewpwdWJsaWM6CiAgICB2b2lkIGRvSXQoUEJhc2UgKmJhc2UpCiAgICB7CiAgICAgICAgaW50ZXJuYWxEb0l0KGJhc2UpOwogICAgfQoKcHJvdGVjdGVkOgogICAgdmlydHVhbCB2b2lkIGludGVybmFsRG9JdChQQmFzZSAqYmFzZSkgPSAwOwp9OwoKdXNpbmcgY2FsbGJhY2tfdHlwZSA9IHZvaWQoKikoU0Jhc2UqLCBQQmFzZSopOwp1c2luZyBtYXBfdHlwZSA9IHN0ZDo6dW5vcmRlcmVkX21hcDxzdGQ6OnR5cGVfaW5kZXgsIGNhbGxiYWNrX3R5cGU+OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFAsIGNhbGxiYWNrX3R5cGUgRm5jPgpzdHJ1Y3QgcGFpcl90eXBlIHt9OwoKdGVtcGxhdGUgPGNsYXNzIC4uLiBQYWlycz4KY2xhc3MgQmFzaWNTIDogcHVibGljIFNCYXNlCnsKcHJvdGVjdGVkOgogICAgdm9pZCBpbnRlcm5hbERvSXQoUEJhc2UgKmJhc2UpIG92ZXJyaWRlCiAgICB7CiAgICAgICAgbWFwX1t0eXBlaWQoKmJhc2UpXSh0aGlzLCBiYXNlKTsKICAgIH0KCnByaXZhdGU6CiAgICBzdGF0aWMgbWFwX3R5cGUgbWFwXzsKfTsKCm5hbWVzcGFjZSBkZXRhaWwKewogICAgdGVtcGxhdGUgPGNsYXNzIC4uLiBQYWlycz4KICAgIHN0cnVjdCBtYXBfZ2V0dGVyOwoKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBQLCBjYWxsYmFja190eXBlIEY+CiAgICBzdHJ1Y3QgbWFwX2dldHRlcjxwYWlyX3R5cGU8UCwgRj4+CiAgICB7CiAgICAgICAgc3RhdGljIG1hcF90eXBlIGdldCgpCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gbWFwX3R5cGV7e3R5cGVpZChQKSwgRn19OwogICAgICAgIH0KICAgIH07CgogICAgdGVtcGxhdGUgPHR5cGVuYW1lIFAsIGNhbGxiYWNrX3R5cGUgRiwgY2xhc3MgLi4uIFRhaWw+CiAgICBzdHJ1Y3QgbWFwX2dldHRlcjxwYWlyX3R5cGU8UCwgRj4sIFRhaWwuLi4+CiAgICB7CiAgICAgICAgc3RhdGljIG1hcF90eXBlIGdldCgpCiAgICAgICAgewogICAgICAgICAgICBhdXRvIG0gPSBtYXBfZ2V0dGVyPFRhaWwuLi4+OjpnZXQoKTsKICAgICAgICAgICAgbS5lbXBsYWNlKHR5cGVpZChQKSwgRik7CiAgICAgICAgICAgIHJldHVybiBtOwogICAgICAgIH0KICAgIH07Cn0KCnRlbXBsYXRlIDxjbGFzcyAuLi4gUGFpcnM+Cm1hcF90eXBlIEJhc2ljUzxQYWlycy4uLj46Om1hcF8gID0gZGV0YWlsOjptYXBfZ2V0dGVyPFBhaXJzLi4uPjo6Z2V0KCk7CgojaW5jbHVkZSA8aW9zdHJlYW0+Cgp2b2lkIHMxcDFEb0l0KFNCYXNlKiwgUEJhc2UqKQp7CiAgICBzdGQ6OmNvdXQgPDwgIlMxIFAxXG4iOwp9Cgp2b2lkIHMxcDJEb0l0KFNCYXNlKiwgUEJhc2UqKQp7CiAgICBzdGQ6OmNvdXQgPDwgIlMxIFAyXG4iOwp9CgpjbGFzcyBTMSA6IHB1YmxpYyBCYXNpY1M8cGFpcl90eXBlPFAxLCBzMXAxRG9JdD4sIHBhaXJfdHlwZTxQMiwgczFwMkRvSXQ+PiB7fTsKCnZvaWQgczJwMURvSXQoU0Jhc2UqLCBQQmFzZSopCnsKICAgIHN0ZDo6Y291dCA8PCAiUzIgUDFcbiI7Cn0KCnZvaWQgczJwMkRvSXQoU0Jhc2UqLCBQQmFzZSopCnsKICAgIHN0ZDo6Y291dCA8PCAiUzIgUDJcbiI7Cn0KCmNsYXNzIFMyIDogcHVibGljIEJhc2ljUzxwYWlyX3R5cGU8UDEsIHMycDFEb0l0PiwgcGFpcl90eXBlPFAyLCBzMnAyRG9JdD4+IHt9OwoKaW50IG1haW4oKQp7CiAgICBTMSBzMTsKICAgIFMyIHMyOwogICAgUDEgcDE7CiAgICBQMiBwMjsKCiAgICBTQmFzZSAmc2Jhc2UxID0gczE7CiAgICBTQmFzZSAmc2Jhc2UyID0gczI7CiAgICBQQmFzZSAmcGJhc2UxID0gcDE7CiAgICBQQmFzZSAmcGJhc2UyID0gcDI7CgogICAgc2Jhc2UxLmRvSXQoJnBiYXNlMSk7CiAgICBzYmFzZTEuZG9JdCgmcGJhc2UyKTsKICAgIHNiYXNlMi5kb0l0KCZwYmFzZTEpOwogICAgc2Jhc2UyLmRvSXQoJnBiYXNlMik7Cn0K