#include <stdio.h>
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
#define D2M(NAME,FUNC) \
template <typename T> \
struct NAME \
{\
template <typename V1, typename V2, typename ...Args> \
T operator()(const std::vector<V1>& v1, const std::vector<V2>& v2, Args&&... args) const { return FUNC(v1, v2, std::forward<Args>(args)...); }\
}
#define D1M(FUNC) \
template <typename T> \
struct NAME \
{\
template <typename V1, typename ...Args> \
T operator()(const std::vector<V1>& v1, Args&&... args) const { return FUNC(v1, std::forward<Args>(args)...); }\
}
enum typeData
{
ValueDouble,
ValueFloat
};
struct data
{
typeData TypeData;
vector<double> getDoubleValues() const { return vector<double>(); }
vector<float> getFloatValues() const { return vector<float>(); }
};
template <typename R, typename F, typename ...Args>
R Dispatch2(const data& d1, const data& d2, F f, Args&&... args)
{
if (d1.TypeData == ValueDouble && d2.TypeData == ValueDouble)
return f(d1.getDoubleValues(), d2.getDoubleValues(), std::forward<Args>(args)...);
if (d1.TypeData == ValueDouble && d2.TypeData == ValueFloat)
return f(d1.getDoubleValues(), d2.getFloatValues(), std::forward<Args>(args)...);
if (d1.TypeData == ValueFloat && d2.TypeData == ValueDouble)
return f(d1.getFloatValues(), d2.getDoubleValues(), std::forward<Args>(args)...);
if (d1.TypeData == ValueFloat && d2.TypeData == ValueFloat)
return f(d1.getFloatValues(), d2.getFloatValues(), std::forward<Args>(args)...);
}
template <typename R, typename F, typename ...Args>
R Dispatch(const data& d1, F f, Args&&... args)
{
if (d1.TypeData == ValueDouble)
return f(d1.getDoubleValues(), std::forward<Args>(args)...);
if (d1.TypeData == ValueFloat)
return f(d1.getFloatValues(), std::forward<Args>(args)...);
}
//usage
struct Context {}; //for additional args
int func2(const std::vector<double>& v1, const std::vector<double>& v2, const Context& ctx)
{
return 1;
}
int func2(const std::vector<double>& v1, const std::vector<float>& v2, const Context& ctx)
{
return 2;
}
int func2(const std::vector<float>& v1, const std::vector<double>& v2, const Context& ctx)
{
return 3;
}
int func2(const std::vector<float>& v1, const std::vector<float>& v2, const Context& ctx)
{
return 4;
}
D2M(Dfic,func2);
int main()
{
data d1;
d1.TypeData = ValueDouble;
data d2;
d2.TypeData = ValueFloat;
Context ctx;
int h1 = Dispatch2<int>(d1, d2, Dfic<int>(), ctx);
cout << "h1 = " << h1 << endl;
d1.TypeData = ValueFloat;
int h2 = Dispatch2<int>(d1, d2, Dfic<int>(), ctx);
cout << "h2 = " << h2 << endl;
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPGZ1bmN0aW9uYWw+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CiAKI2RlZmluZSBEMk0oTkFNRSxGVU5DKSBcCnRlbXBsYXRlIDx0eXBlbmFtZSBUPiBcCnN0cnVjdCBOQU1FIFwKe1wKICAgICAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVjEsIHR5cGVuYW1lIFYyLCB0eXBlbmFtZSAuLi5BcmdzPiBcCiAgICAgICAgVCBvcGVyYXRvcigpKGNvbnN0IHN0ZDo6dmVjdG9yPFYxPiYgdjEsIGNvbnN0IHN0ZDo6dmVjdG9yPFYyPiYgdjIsIEFyZ3MmJi4uLiBhcmdzKSBjb25zdCB7IHJldHVybiBGVU5DKHYxLCB2Miwgc3RkOjpmb3J3YXJkPEFyZ3M+KGFyZ3MpLi4uKTsgfVwKfQogCiNkZWZpbmUgRDFNKEZVTkMpIFwKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+IFwKc3RydWN0IE5BTUUgXAp7XAogICAgICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBWMSwgdHlwZW5hbWUgLi4uQXJncz4gXAogICAgICAgIFQgb3BlcmF0b3IoKShjb25zdCBzdGQ6OnZlY3RvcjxWMT4mIHYxLCBBcmdzJiYuLi4gYXJncykgY29uc3QgeyByZXR1cm4gRlVOQyh2MSwgIHN0ZDo6Zm9yd2FyZDxBcmdzPihhcmdzKS4uLik7IH1cCn0KIAplbnVtIHR5cGVEYXRhCnsKICAgICAgICBWYWx1ZURvdWJsZSwKICAgICAgICBWYWx1ZUZsb2F0Cn07CiAKc3RydWN0IGRhdGEKewogICAgICAgIHR5cGVEYXRhIFR5cGVEYXRhOwogICAgICAgIHZlY3Rvcjxkb3VibGU+IGdldERvdWJsZVZhbHVlcygpIGNvbnN0IHsgcmV0dXJuIHZlY3Rvcjxkb3VibGU+KCk7IH0KICAgICAgICB2ZWN0b3I8ZmxvYXQ+IGdldEZsb2F0VmFsdWVzKCkgY29uc3QgeyByZXR1cm4gdmVjdG9yPGZsb2F0PigpOyB9Cn07CiAKdGVtcGxhdGUgPHR5cGVuYW1lIFIsIHR5cGVuYW1lIEYsIHR5cGVuYW1lIC4uLkFyZ3M+ClIgRGlzcGF0Y2gyKGNvbnN0IGRhdGEmIGQxLCBjb25zdCBkYXRhJiBkMiwgRiBmLCBBcmdzJiYuLi4gYXJncykKewogICAgICAgIGlmIChkMS5UeXBlRGF0YSA9PSBWYWx1ZURvdWJsZSAmJiBkMi5UeXBlRGF0YSA9PSBWYWx1ZURvdWJsZSkKICAgICAgICAgICAgICAgIHJldHVybiBmKGQxLmdldERvdWJsZVZhbHVlcygpLCBkMi5nZXREb3VibGVWYWx1ZXMoKSwgc3RkOjpmb3J3YXJkPEFyZ3M+KGFyZ3MpLi4uKTsKIAogICAgICAgIGlmIChkMS5UeXBlRGF0YSA9PSBWYWx1ZURvdWJsZSAmJiBkMi5UeXBlRGF0YSA9PSBWYWx1ZUZsb2F0KQogICAgICAgICAgICAgICAgcmV0dXJuIGYoZDEuZ2V0RG91YmxlVmFsdWVzKCksIGQyLmdldEZsb2F0VmFsdWVzKCksIHN0ZDo6Zm9yd2FyZDxBcmdzPihhcmdzKS4uLik7CiAKICAgICAgICBpZiAoZDEuVHlwZURhdGEgPT0gVmFsdWVGbG9hdCAmJiBkMi5UeXBlRGF0YSA9PSBWYWx1ZURvdWJsZSkKICAgICAgICAgICAgICAgIHJldHVybiBmKGQxLmdldEZsb2F0VmFsdWVzKCksIGQyLmdldERvdWJsZVZhbHVlcygpLCBzdGQ6OmZvcndhcmQ8QXJncz4oYXJncykuLi4pOwogCiAgICAgICAgaWYgKGQxLlR5cGVEYXRhID09IFZhbHVlRmxvYXQgJiYgZDIuVHlwZURhdGEgPT0gVmFsdWVGbG9hdCkKICAgICAgICAgICAgICAgIHJldHVybiBmKGQxLmdldEZsb2F0VmFsdWVzKCksIGQyLmdldEZsb2F0VmFsdWVzKCksIHN0ZDo6Zm9yd2FyZDxBcmdzPihhcmdzKS4uLik7Cn0KIAp0ZW1wbGF0ZSA8dHlwZW5hbWUgUiwgdHlwZW5hbWUgRiwgdHlwZW5hbWUgLi4uQXJncz4KUiBEaXNwYXRjaChjb25zdCBkYXRhJiBkMSwgRiBmLCBBcmdzJiYuLi4gYXJncykKewogICAgICAgIGlmIChkMS5UeXBlRGF0YSA9PSBWYWx1ZURvdWJsZSkKICAgICAgICAgICAgICAgICByZXR1cm4gZihkMS5nZXREb3VibGVWYWx1ZXMoKSwgc3RkOjpmb3J3YXJkPEFyZ3M+KGFyZ3MpLi4uKTsKIAogICAgICAgIGlmIChkMS5UeXBlRGF0YSA9PSBWYWx1ZUZsb2F0KQogICAgICAgICAgICAgICAgIHJldHVybiBmKGQxLmdldEZsb2F0VmFsdWVzKCksIHN0ZDo6Zm9yd2FyZDxBcmdzPihhcmdzKS4uLik7Cn0KIAovL3VzYWdlCnN0cnVjdCBDb250ZXh0IHt9OyAvL2ZvciBhZGRpdGlvbmFsIGFyZ3MKaW50IGZ1bmMyKGNvbnN0IHN0ZDo6dmVjdG9yPGRvdWJsZT4mIHYxLCBjb25zdCBzdGQ6OnZlY3Rvcjxkb3VibGU+JiB2MiwgY29uc3QgQ29udGV4dCYgY3R4KQp7CnJldHVybiAxOwp9CiAKaW50IGZ1bmMyKGNvbnN0IHN0ZDo6dmVjdG9yPGRvdWJsZT4mIHYxLCBjb25zdCBzdGQ6OnZlY3RvcjxmbG9hdD4mIHYyLCBjb25zdCBDb250ZXh0JiBjdHgpCnsKcmV0dXJuIDI7Cn0KIAppbnQgZnVuYzIoY29uc3Qgc3RkOjp2ZWN0b3I8ZmxvYXQ+JiB2MSwgY29uc3Qgc3RkOjp2ZWN0b3I8ZG91YmxlPiYgdjIsIGNvbnN0IENvbnRleHQmIGN0eCkKewpyZXR1cm4gMzsKfQogCmludCBmdW5jMihjb25zdCBzdGQ6OnZlY3RvcjxmbG9hdD4mIHYxLCBjb25zdCBzdGQ6OnZlY3RvcjxmbG9hdD4mIHYyLCBjb25zdCBDb250ZXh0JiBjdHgpCnsKcmV0dXJuIDQ7Cn0KCiAKRDJNKERmaWMsZnVuYzIpOwogCmludCBtYWluKCkKewogICAgICAgIGRhdGEgZDE7CiAgICAgICAgZDEuVHlwZURhdGEgPSBWYWx1ZURvdWJsZTsKIAogICAgICAgIGRhdGEgZDI7CiAgICAgICAgZDIuVHlwZURhdGEgPSBWYWx1ZUZsb2F0OwogCiAgICAgICAgQ29udGV4dCBjdHg7CiAKICAgICAgICBpbnQgaDEgPSBEaXNwYXRjaDI8aW50PihkMSwgZDIsIERmaWM8aW50PigpLCBjdHgpOwogICAgICAgIGNvdXQgPDwgImgxID0gIiA8PCBoMSA8PCBlbmRsOwogCiAgICAgICAgZDEuVHlwZURhdGEgPSBWYWx1ZUZsb2F0OwogICAgICAgIGludCBoMiA9IERpc3BhdGNoMjxpbnQ+KGQxLCBkMiwgRGZpYzxpbnQ+KCksIGN0eCk7CiAgICAgICAgY291dCA8PCAiaDIgPSAiIDw8IGgyIDw8IGVuZGw7CiAgICAgICAgcmV0dXJuIDA7Cn0=