#include <iostream>
#include <vector>
using namespace std;
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)...);
}
//usage
struct Context {}; //for additional args
template <typename T>
struct D3
{
template <typename V, typename ...Args>
T operator()(const std::vector<V>& v1, const std::vector<V>& v2, Args&&... args) const { return 1; }
template <typename V1, typename V2, typename ...Args>
T operator()(const std::vector<V1>& v1, const std::vector<V2>& v2, Args&&... args) const { return 2; }
};
int main()
{
data d1;
d1.TypeData = ValueDouble;
data d2;
d2.TypeData = ValueFloat;
Context ctx;
int h1 = Dispatch2<int>(d1, d2, D3<int>(), ctx);
cout << "h1 = " << h1 << endl;
d1.TypeData = ValueFloat;
int h2 = Dispatch2<int>(d1, d2, D3<int>(), ctx);
cout << "h2 = " << h2 << endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCmVudW0gdHlwZURhdGEKewoJVmFsdWVEb3VibGUsCglWYWx1ZUZsb2F0Cn07CgpzdHJ1Y3QgZGF0YQp7CiAgICB0eXBlRGF0YSBUeXBlRGF0YTsKICAgIHZlY3Rvcjxkb3VibGU+IGdldERvdWJsZVZhbHVlcygpIGNvbnN0IHsgcmV0dXJuIHZlY3Rvcjxkb3VibGU+KCk7IH0KICAgIHZlY3RvcjxmbG9hdD4gZ2V0RmxvYXRWYWx1ZXMoKSBjb25zdCB7IHJldHVybiB2ZWN0b3I8ZmxvYXQ+KCk7IH0KfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBSLCB0eXBlbmFtZSBGLCB0eXBlbmFtZSAuLi5BcmdzPgpSIERpc3BhdGNoMihjb25zdCBkYXRhJiBkMSwgY29uc3QgZGF0YSYgZDIsIEYgZiwgQXJncyYmLi4uIGFyZ3MpCnsKICBpZiAoZDEuVHlwZURhdGEgPT0gVmFsdWVEb3VibGUgJiYgZDIuVHlwZURhdGEgPT0gVmFsdWVEb3VibGUpCglyZXR1cm4gZihkMS5nZXREb3VibGVWYWx1ZXMoKSwgZDIuZ2V0RG91YmxlVmFsdWVzKCksIHN0ZDo6Zm9yd2FyZDxBcmdzPihhcmdzKS4uLik7CgkKICBpZiAoZDEuVHlwZURhdGEgPT0gVmFsdWVEb3VibGUgJiYgZDIuVHlwZURhdGEgPT0gVmFsdWVGbG9hdCkKCXJldHVybiBmKGQxLmdldERvdWJsZVZhbHVlcygpLCBkMi5nZXRGbG9hdFZhbHVlcygpLCBzdGQ6OmZvcndhcmQ8QXJncz4oYXJncykuLi4pOwoJCiAgaWYgKGQxLlR5cGVEYXRhID09IFZhbHVlRmxvYXQgJiYgZDIuVHlwZURhdGEgPT0gVmFsdWVEb3VibGUpCglyZXR1cm4gZihkMS5nZXRGbG9hdFZhbHVlcygpLCBkMi5nZXREb3VibGVWYWx1ZXMoKSwgc3RkOjpmb3J3YXJkPEFyZ3M+KGFyZ3MpLi4uKTsKCQogIGlmIChkMS5UeXBlRGF0YSA9PSBWYWx1ZUZsb2F0ICYmIGQyLlR5cGVEYXRhID09IFZhbHVlRmxvYXQpCglyZXR1cm4gZihkMS5nZXRGbG9hdFZhbHVlcygpLCBkMi5nZXRGbG9hdFZhbHVlcygpLCBzdGQ6OmZvcndhcmQ8QXJncz4oYXJncykuLi4pOwp9CgovL3VzYWdlCnN0cnVjdCBDb250ZXh0IHt9OyAvL2ZvciBhZGRpdGlvbmFsIGFyZ3MKCnRlbXBsYXRlIDx0eXBlbmFtZSBUPgpzdHJ1Y3QgRDMKewogIHRlbXBsYXRlIDx0eXBlbmFtZSBWLCB0eXBlbmFtZSAuLi5BcmdzPgogIFQgb3BlcmF0b3IoKShjb25zdCBzdGQ6OnZlY3RvcjxWPiYgdjEsIGNvbnN0IHN0ZDo6dmVjdG9yPFY+JiB2MiwgQXJncyYmLi4uIGFyZ3MpIGNvbnN0IHsgcmV0dXJuIDE7IH0KICAKICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVjEsIHR5cGVuYW1lIFYyLCB0eXBlbmFtZSAuLi5BcmdzPgogIFQgb3BlcmF0b3IoKShjb25zdCBzdGQ6OnZlY3RvcjxWMT4mIHYxLCBjb25zdCBzdGQ6OnZlY3RvcjxWMj4mIHYyLCBBcmdzJiYuLi4gYXJncykgY29uc3QgeyByZXR1cm4gMjsgfQp9OwoKaW50IG1haW4oKQp7CglkYXRhIGQxOwogICAgZDEuVHlwZURhdGEgPSBWYWx1ZURvdWJsZTsKCiAgICBkYXRhIGQyOwogICAgZDIuVHlwZURhdGEgPSBWYWx1ZUZsb2F0OwogICAgCiAgICBDb250ZXh0IGN0eDsKICAgIAogICAgaW50IGgxID0gRGlzcGF0Y2gyPGludD4oZDEsIGQyLCBEMzxpbnQ+KCksIGN0eCk7CiAgICBjb3V0IDw8ICJoMSA9ICIgPDwgaDEgPDwgZW5kbDsKICAgIAogICAgZDEuVHlwZURhdGEgPSBWYWx1ZUZsb2F0OwogICAgaW50IGgyID0gRGlzcGF0Y2gyPGludD4oZDEsIGQyLCBEMzxpbnQ+KCksIGN0eCk7CiAgICBjb3V0IDw8ICJoMiA9ICIgPDwgaDIgPDwgZW5kbDsKCXJldHVybiAwOwp9