#include <unordered_map>
#include <string>
#include <utility>
#include <typeinfo>
#include <stdexcept>
#include <iostream>
struct BeliefCondFunc
{
using cb_type = bool(*)();
using map_val = std::pair<cb_type, std::type_info const*>;
static std::unordered_map<std::string, map_val> const FuncMap;
static bool Greater(int A, int B)
{
return A > B;
}
static bool Between(float A, float B, float C)
{
return A > B && A < C;
}
template<typename ...Args>
static map_val make_map_val(bool (*func)(Args...)) {
return std::make_pair(reinterpret_cast<cb_type>(func),
&typeid(decltype(func)));
}
template<typename ...Args>
static bool call(std::string const& key, Args&&... args){
using prototype = bool(*)(Args...);
auto& func_n_typeid = FuncMap.at(key);
if (typeid(prototype) != *func_n_typeid.second )
throw std::domain_error("Prototype mismatch");
return reinterpret_cast<prototype>(func_n_typeid.first)(std::forward<Args>(args)...);
};
};
std::unordered_map<std::string, BeliefCondFunc::map_val> const BeliefCondFunc::FuncMap {
{"Greater", make_map_val(&BeliefCondFunc::Greater) },
{"Between", make_map_val(&BeliefCondFunc::Between) }
};
int main() {
BeliefCondFunc::call("Greater", 1, 2);
try {
BeliefCondFunc::call("Lesser", 1, 2);
} catch (std::out_of_range&) {
std::cout << "No such function\n";
}
try {
BeliefCondFunc::call("Between", 1, 2);
} catch (std::domain_error&) {
std::cout << "Wrong number of arguments\n";
}
return 0;
}
I2luY2x1ZGUgPHVub3JkZXJlZF9tYXA+CiNpbmNsdWRlIDxzdHJpbmc+CiNpbmNsdWRlIDx1dGlsaXR5PgojaW5jbHVkZSA8dHlwZWluZm8+CiNpbmNsdWRlIDxzdGRleGNlcHQ+CiNpbmNsdWRlIDxpb3N0cmVhbT4KCnN0cnVjdCBCZWxpZWZDb25kRnVuYwp7CiAgICB1c2luZyBjYl90eXBlID0gYm9vbCgqKSgpOwogICAgdXNpbmcgbWFwX3ZhbCA9IHN0ZDo6cGFpcjxjYl90eXBlLCBzdGQ6OnR5cGVfaW5mbyBjb25zdCo+OwogICAgc3RhdGljIHN0ZDo6dW5vcmRlcmVkX21hcDxzdGQ6OnN0cmluZywgbWFwX3ZhbD4gY29uc3QgRnVuY01hcDsKICAgIAogICAgc3RhdGljIGJvb2wgR3JlYXRlcihpbnQgQSwgaW50IEIpCiAgICB7CiAgICAgICAgcmV0dXJuIEEgPiBCOwogICAgfQoKICAgIHN0YXRpYyBib29sIEJldHdlZW4oZmxvYXQgQSwgZmxvYXQgQiwgZmxvYXQgQykKICAgIHsKICAgICAgICByZXR1cm4gQSA+IEIgJiYgQSA8IEM7CiAgICB9CiAgICAKICAgIHRlbXBsYXRlPHR5cGVuYW1lIC4uLkFyZ3M+CiAgICBzdGF0aWMgbWFwX3ZhbCBtYWtlX21hcF92YWwoYm9vbCAoKmZ1bmMpKEFyZ3MuLi4pKSB7CiAgICAJCiAgICAJcmV0dXJuIHN0ZDo6bWFrZV9wYWlyKHJlaW50ZXJwcmV0X2Nhc3Q8Y2JfdHlwZT4oZnVuYyksIAogICAgCSAgICAgICAgICAgICAgICAgICAgICAmdHlwZWlkKGRlY2x0eXBlKGZ1bmMpKSk7CiAgICB9CiAgICAKICAgIHRlbXBsYXRlPHR5cGVuYW1lIC4uLkFyZ3M+CiAgICBzdGF0aWMgYm9vbCBjYWxsKHN0ZDo6c3RyaW5nIGNvbnN0JiBrZXksIEFyZ3MmJi4uLiBhcmdzKXsKICAgICAgdXNpbmcgcHJvdG90eXBlID0gYm9vbCgqKShBcmdzLi4uKTsKICAgICAgCiAgICAgIGF1dG8mIGZ1bmNfbl90eXBlaWQgPSBGdW5jTWFwLmF0KGtleSk7CiAgICAgIAogICAgICBpZiAodHlwZWlkKHByb3RvdHlwZSkgIT0gKmZ1bmNfbl90eXBlaWQuc2Vjb25kICkKICAgICAgICB0aHJvdyBzdGQ6OmRvbWFpbl9lcnJvcigiUHJvdG90eXBlIG1pc21hdGNoIik7CiAgICAgIAogICAgICByZXR1cm4gcmVpbnRlcnByZXRfY2FzdDxwcm90b3R5cGU+KGZ1bmNfbl90eXBlaWQuZmlyc3QpKHN0ZDo6Zm9yd2FyZDxBcmdzPihhcmdzKS4uLik7CiAgICB9Owp9OwoKc3RkOjp1bm9yZGVyZWRfbWFwPHN0ZDo6c3RyaW5nLCBCZWxpZWZDb25kRnVuYzo6bWFwX3ZhbD4gY29uc3QgQmVsaWVmQ29uZEZ1bmM6OkZ1bmNNYXAgewogIHsiR3JlYXRlciIsIG1ha2VfbWFwX3ZhbCgmQmVsaWVmQ29uZEZ1bmM6OkdyZWF0ZXIpIH0sCiAgeyJCZXR3ZWVuIiwgbWFrZV9tYXBfdmFsKCZCZWxpZWZDb25kRnVuYzo6QmV0d2VlbikgfQp9OwoKaW50IG1haW4oKSB7CglCZWxpZWZDb25kRnVuYzo6Y2FsbCgiR3JlYXRlciIsIDEsIDIpOwoJCgl0cnkgewoJCUJlbGllZkNvbmRGdW5jOjpjYWxsKCJMZXNzZXIiLCAxLCAyKTsKCX0gY2F0Y2ggKHN0ZDo6b3V0X29mX3JhbmdlJikgewoJCXN0ZDo6Y291dCA8PCAiTm8gc3VjaCBmdW5jdGlvblxuIjsKCX0KCQoJdHJ5IHsKCQlCZWxpZWZDb25kRnVuYzo6Y2FsbCgiQmV0d2VlbiIsIDEsIDIpOwoJfSBjYXRjaCAoc3RkOjpkb21haW5fZXJyb3ImKSB7CgkJc3RkOjpjb3V0IDw8ICJXcm9uZyBudW1iZXIgb2YgYXJndW1lbnRzXG4iOwoJfQoJCglyZXR1cm4gMDsKfQ==