#include <iostream>
#include <functional>
#include <tuple>
enum class AnimalType
{
bird,
mammal,
lizard,
fish,
};
template<int LEGCOUNT, typename T>
class AbstractAnimal
{
public:
T printLegCount() { std::cout << LEGCOUNT << std::endl; return 0; }
};
class Mammal : public AbstractAnimal<4, double>{};
class Bird : public AbstractAnimal<2, int>{};
class Lizard : public AbstractAnimal<4, float>{};
class Fish : public AbstractAnimal<0, long long>{};
using AnimalTuple = std::tuple<Bird, Mammal, Lizard, Fish>; // Same order as enum AnimalType
template <typename T, typename F>
std::function<void()> call_with_default(F&& f)
{
return [f]() {f(T{});};
}
template <typename F, std::size_t...Is>
void dispatch(AnimalType animalType, F&& f, std::index_sequence<Is...>)
{
std::function<void()> fs[] = {call_with_default<std::tuple_element_t<Is, AnimalTuple>>(f)...};
fs[static_cast<int>(animalType)]();
}
template <typename F>
void dispatch(AnimalType animalType, F f)
{
dispatch(animalType, f, std::make_index_sequence<std::tuple_size<AnimalTuple>::value>{});
}
void printLegCount(AnimalType animalType)
{
auto legCountPrinter = [](auto t) { t.printLegCount(); };
dispatch(animalType, legCountPrinter);
}
int main()
{
printLegCount(AnimalType::mammal);
printLegCount(AnimalType::fish);
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8ZnVuY3Rpb25hbD4KI2luY2x1ZGUgPHR1cGxlPgoKZW51bSBjbGFzcyBBbmltYWxUeXBlCnsKICAgYmlyZCwKICAgbWFtbWFsLAogICBsaXphcmQsCiAgIGZpc2gsCn07Cgp0ZW1wbGF0ZTxpbnQgTEVHQ09VTlQsIHR5cGVuYW1lIFQ+CmNsYXNzIEFic3RyYWN0QW5pbWFsCnsKcHVibGljOgogICBUIHByaW50TGVnQ291bnQoKSB7IHN0ZDo6Y291dCA8PCBMRUdDT1VOVCA8PCBzdGQ6OmVuZGw7IHJldHVybiAwOyB9Cn07CgpjbGFzcyBNYW1tYWwgOiBwdWJsaWMgQWJzdHJhY3RBbmltYWw8NCwgZG91YmxlPnt9OwpjbGFzcyBCaXJkIDogcHVibGljIEFic3RyYWN0QW5pbWFsPDIsIGludD57fTsKY2xhc3MgTGl6YXJkIDogcHVibGljIEFic3RyYWN0QW5pbWFsPDQsIGZsb2F0Pnt9OwpjbGFzcyBGaXNoIDogcHVibGljIEFic3RyYWN0QW5pbWFsPDAsIGxvbmcgbG9uZz57fTsKCnVzaW5nIEFuaW1hbFR1cGxlID0gc3RkOjp0dXBsZTxCaXJkLCBNYW1tYWwsIExpemFyZCwgRmlzaD47IC8vIFNhbWUgb3JkZXIgYXMgZW51bSBBbmltYWxUeXBlCgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdHlwZW5hbWUgRj4Kc3RkOjpmdW5jdGlvbjx2b2lkKCk+IGNhbGxfd2l0aF9kZWZhdWx0KEYmJiBmKQp7CiAgICByZXR1cm4gW2ZdKCkge2YoVHt9KTt9Owp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgRiwgc3RkOjpzaXplX3QuLi5Jcz4Kdm9pZCBkaXNwYXRjaChBbmltYWxUeXBlIGFuaW1hbFR5cGUsIEYmJiBmLCBzdGQ6OmluZGV4X3NlcXVlbmNlPElzLi4uPikKewogICAgc3RkOjpmdW5jdGlvbjx2b2lkKCk+IGZzW10gPSB7Y2FsbF93aXRoX2RlZmF1bHQ8c3RkOjp0dXBsZV9lbGVtZW50X3Q8SXMsIEFuaW1hbFR1cGxlPj4oZikuLi59OwogICAgZnNbc3RhdGljX2Nhc3Q8aW50PihhbmltYWxUeXBlKV0oKTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIEY+CnZvaWQgZGlzcGF0Y2goQW5pbWFsVHlwZSBhbmltYWxUeXBlLCBGIGYpCnsKICAgIGRpc3BhdGNoKGFuaW1hbFR5cGUsIGYsIHN0ZDo6bWFrZV9pbmRleF9zZXF1ZW5jZTxzdGQ6OnR1cGxlX3NpemU8QW5pbWFsVHVwbGU+Ojp2YWx1ZT57fSk7Cn0KCnZvaWQgcHJpbnRMZWdDb3VudChBbmltYWxUeXBlIGFuaW1hbFR5cGUpCnsKICAgIGF1dG8gbGVnQ291bnRQcmludGVyID0gW10oYXV0byB0KSB7IHQucHJpbnRMZWdDb3VudCgpOyB9OwogICAgZGlzcGF0Y2goYW5pbWFsVHlwZSwgbGVnQ291bnRQcmludGVyKTsKfQoKaW50IG1haW4oKQp7CiAgICBwcmludExlZ0NvdW50KEFuaW1hbFR5cGU6Om1hbW1hbCk7CiAgICBwcmludExlZ0NvdW50KEFuaW1hbFR5cGU6OmZpc2gpOwp9