#include <iostream>
#include <map>
#include <type_traits>
#include <utility>
using namespace std;
struct one {
int foo(const int) { return 0; }
int bar() { return 0; }
};
struct two {
int foo(const int) { return 1; }
};
struct three {
int foo(const int) { return 2; }
int bar() { return 2; }
};
struct owner {
map<int, one> ones;
map<int, two> twos;
map<int, three> threes;
template<class T, class... Ts>
struct overload : T, overload<Ts...> {
using T::operator();
using overload<Ts...>::operator();
overload(T t, Ts... ts) : T(t), overload<Ts...>(ts...) {}
};
template<class T>
struct overload<T> : T {
using T::operator();
overload(T t) : T(t) {}
};
template<class...Ts>
overload<Ts...> make_overload(Ts... ts) {
return overload<Ts...>(ts...);
}
struct fallback_t { template<class T> fallback_t(T&&) {} };
template <typename T, typename Func>
int callFunc(T& param, const Func& func) {
return func(param);
}
template <typename T>
int findObject(int key, const T& func) {
if(ones.count(key) != 0U) {
return callFunc(ones[key], func);
}
else if(twos.count(key) != 0U) {
return callFunc(twos[key], func);
}
else {
return callFunc(threes[key], func);
}
}
int foo(const int key, const int param) { return findObject(key, [&](auto& value) { return value.foo(param); }); }
int bar(const int key) {
return findObject(key, make_overload(
[](const auto& value) -> decltype(int(value.bar())) { return value.bar(); },
[](fallback_t) -> int { std::cout << "fallback\n"; return 13; }
));
}
};
int main() {
owner myOwner;
myOwner.ones.insert(make_pair(0, one()));
myOwner.twos.insert(make_pair(1, two()));
myOwner.threes.insert(make_pair(2, three()));
myOwner.foo(2, 1);
cout << myOwner.bar(1) << endl;
cout << myOwner.bar(2) << endl;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8bWFwPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CiNpbmNsdWRlIDx1dGlsaXR5PgoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCnN0cnVjdCBvbmUgewogIGludCBmb28oY29uc3QgaW50KSB7IHJldHVybiAwOyB9CiAgaW50IGJhcigpIHsgcmV0dXJuIDA7IH0KfTsKCnN0cnVjdCB0d28gewogIGludCBmb28oY29uc3QgaW50KSB7IHJldHVybiAxOyB9Cn07CgpzdHJ1Y3QgdGhyZWUgewogIGludCBmb28oY29uc3QgaW50KSB7IHJldHVybiAyOyB9CiAgaW50IGJhcigpIHsgcmV0dXJuIDI7IH0KfTsKCnN0cnVjdCBvd25lciB7CiAgbWFwPGludCwgb25lPiBvbmVzOwogIG1hcDxpbnQsIHR3bz4gdHdvczsKICBtYXA8aW50LCB0aHJlZT4gdGhyZWVzOwoKICB0ZW1wbGF0ZTxjbGFzcyBULCBjbGFzcy4uLiBUcz4KICBzdHJ1Y3Qgb3ZlcmxvYWQgOiBULCBvdmVybG9hZDxUcy4uLj4gewogICAgdXNpbmcgVDo6b3BlcmF0b3IoKTsKICAgIHVzaW5nIG92ZXJsb2FkPFRzLi4uPjo6b3BlcmF0b3IoKTsKICAgIG92ZXJsb2FkKFQgdCwgVHMuLi4gdHMpIDogVCh0KSwgb3ZlcmxvYWQ8VHMuLi4+KHRzLi4uKSB7fQogIH07CgogIHRlbXBsYXRlPGNsYXNzIFQ+CiAgc3RydWN0IG92ZXJsb2FkPFQ+IDogVCB7CiAgICB1c2luZyBUOjpvcGVyYXRvcigpOwogICAgb3ZlcmxvYWQoVCB0KSA6IFQodCkge30KICB9OwoKICB0ZW1wbGF0ZTxjbGFzcy4uLlRzPgogIG92ZXJsb2FkPFRzLi4uPiBtYWtlX292ZXJsb2FkKFRzLi4uIHRzKSB7CiAgICByZXR1cm4gb3ZlcmxvYWQ8VHMuLi4+KHRzLi4uKTsKICB9CgogIHN0cnVjdCBmYWxsYmFja190IHsgdGVtcGxhdGU8Y2xhc3MgVD4gZmFsbGJhY2tfdChUJiYpIHt9IH07CgogIHRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBGdW5jPgogIGludCBjYWxsRnVuYyhUJiBwYXJhbSwgY29uc3QgRnVuYyYgZnVuYykgewogICAgcmV0dXJuIGZ1bmMocGFyYW0pOwogIH0KCiAgdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CiAgaW50IGZpbmRPYmplY3QoaW50IGtleSwgY29uc3QgVCYgZnVuYykgewogICAgaWYob25lcy5jb3VudChrZXkpICE9IDBVKSB7CiAgICAgIHJldHVybiBjYWxsRnVuYyhvbmVzW2tleV0sIGZ1bmMpOwogICAgfQogICAgZWxzZSBpZih0d29zLmNvdW50KGtleSkgIT0gMFUpIHsKICAgICAgcmV0dXJuIGNhbGxGdW5jKHR3b3Nba2V5XSwgZnVuYyk7CiAgICB9CiAgICBlbHNlIHsKICAgICAgcmV0dXJuIGNhbGxGdW5jKHRocmVlc1trZXldLCBmdW5jKTsKICAgIH0KICB9CgogIGludCBmb28oY29uc3QgaW50IGtleSwgY29uc3QgaW50IHBhcmFtKSB7IHJldHVybiBmaW5kT2JqZWN0KGtleSwgWyZdKGF1dG8mIHZhbHVlKSB7IHJldHVybiB2YWx1ZS5mb28ocGFyYW0pOyB9KTsgfQogIGludCBiYXIoY29uc3QgaW50IGtleSkgewogICAgcmV0dXJuIGZpbmRPYmplY3Qoa2V5LCBtYWtlX292ZXJsb2FkKAogICAgICBbXShjb25zdCBhdXRvJiB2YWx1ZSkgLT4gZGVjbHR5cGUoaW50KHZhbHVlLmJhcigpKSkgeyByZXR1cm4gdmFsdWUuYmFyKCk7IH0sCiAgICAgIFtdKGZhbGxiYWNrX3QpIC0+IGludCB7IHN0ZDo6Y291dCA8PCAiZmFsbGJhY2tcbiI7IHJldHVybiAxMzsgfQogICAgICApKTsKICB9Cn07CgppbnQgbWFpbigpIHsKICBvd25lciBteU93bmVyOwoKICBteU93bmVyLm9uZXMuaW5zZXJ0KG1ha2VfcGFpcigwLCBvbmUoKSkpOwogIG15T3duZXIudHdvcy5pbnNlcnQobWFrZV9wYWlyKDEsIHR3bygpKSk7CiAgbXlPd25lci50aHJlZXMuaW5zZXJ0KG1ha2VfcGFpcigyLCB0aHJlZSgpKSk7CgogIG15T3duZXIuZm9vKDIsIDEpOwogIGNvdXQgPDwgbXlPd25lci5iYXIoMSkgPDwgZW5kbDsKICBjb3V0IDw8IG15T3duZXIuYmFyKDIpIDw8IGVuZGw7Cn0=