#include <typeinfo>
#include <typeindex>
#include <unordered_map>
#include <iostream>
using namespace std;
template <typename R>
class MultiFuncObject {
unordered_map<type_index, void (*)()> m_funcs;
public:
MultiFuncObject<R> operator +=( R (* f)() ) {
m_funcs[typeid( R() )] = (void (*)()) f;
return *this;
}
template <typename A1>
MultiFuncObject<R> operator +=( R (* f)(A1) ) {
m_funcs[typeid( R(A1) )] = (void (*)()) f;
return *this;
}
template <typename A1, typename A2>
MultiFuncObject<R> operator +=( R (* f)(A1, A2) ) {
m_funcs[typeid( R(A1, A2) )] = (void (*)()) f;
return *this;
}
template <typename A1, typename A2, typename A3>
MultiFuncObject<R> operator +=( R (* f)(A1, A2, A3) ) {
m_funcs[typeid( R(A1, A2, A3) )] = (void (*)()) f;
return *this;
}
R operator()() const
{
unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R() ));
if (it != m_funcs.end()) {
R (*f)() = ( R (*)() )(it->second);
(*f)();
}
}
template <typename A1>
R operator()(A1 a1) const
{
unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R(A1) ));
if (it != m_funcs.end()) {
R (*f)(A1) = ( R (*)(A1) )(it->second);
(*f)(a1);
}
}
template <typename A1, typename A2>
R operator()(A1 a1, A2 a2) const
{
unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R(A1, A2) ));
if (it != m_funcs.end()) {
R (*f)(A1, A2) = ( R (*)(A1, A2) )(it->second);
(*f)(a1, a2);
}
}
template <typename A1, typename A2, typename A3>
R operator()(A1 a1, A2 a2, A3 a3) const
{
unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R(A1, A2, A3) ));
if (it != m_funcs.end()) {
R (*f)(A1, A2, A3) = ( R (*)(A1, A2, A3) )(it->second);
(*f)(a1, a2, a3);
}
}
};
void _1() {
cout << "_1" << endl;
}
void _2(char x) {
cout << "_2" << " " << x << endl;
}
void _3(int x) {
cout << "_3" << " " << x << endl;
}
void _4(double x) {
cout << "_4" << " " << x << endl;
}
void _5(int a, int b) {
cout << "_5" << " " << a << " " << b << endl;
}
void _6(char a, int b) {
cout << "_6" << " " << a << " " << b << endl;
}
void _7(int a, int b, int c) {
cout << "_7" << " " << a << " " << b << " " << c << endl;
}
int main() {
MultiFuncObject<void> funcs;
funcs += &_1;
funcs += &_2;
funcs += &_3;
funcs += &_4;
funcs += &_5;
funcs += &_6;
funcs += &_7;
funcs();
funcs('a');
funcs(56);
funcs(5.5);
funcs(2, 5);
funcs('q', 6);
funcs(1, 2, 3);
return 0;
}
I2luY2x1ZGUgPHR5cGVpbmZvPgojaW5jbHVkZSA8dHlwZWluZGV4PgojaW5jbHVkZSA8dW5vcmRlcmVkX21hcD4KI2luY2x1ZGUgPGlvc3RyZWFtPgoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCnRlbXBsYXRlIDx0eXBlbmFtZSBSPgpjbGFzcyBNdWx0aUZ1bmNPYmplY3QgewogIHVub3JkZXJlZF9tYXA8dHlwZV9pbmRleCwgdm9pZCAoKikoKT4gbV9mdW5jczsKcHVibGljOgoKICBNdWx0aUZ1bmNPYmplY3Q8Uj4gb3BlcmF0b3IgKz0oIFIgKCogZikoKSApIHsKICAgIG1fZnVuY3NbdHlwZWlkKCBSKCkgKV0gPSAodm9pZCAoKikoKSkgZjsKICAgIHJldHVybiAqdGhpczsKICB9CgogIHRlbXBsYXRlIDx0eXBlbmFtZSBBMT4KICBNdWx0aUZ1bmNPYmplY3Q8Uj4gb3BlcmF0b3IgKz0oIFIgKCogZikoQTEpICkgewogICAgbV9mdW5jc1t0eXBlaWQoIFIoQTEpICldID0gKHZvaWQgKCopKCkpIGY7CiAgICByZXR1cm4gKnRoaXM7CiAgfQoKICB0ZW1wbGF0ZSA8dHlwZW5hbWUgQTEsIHR5cGVuYW1lIEEyPgogIE11bHRpRnVuY09iamVjdDxSPiBvcGVyYXRvciArPSggUiAoKiBmKShBMSwgQTIpICkgewogICAgbV9mdW5jc1t0eXBlaWQoIFIoQTEsIEEyKSApXSA9ICh2b2lkICgqKSgpKSBmOwogICAgcmV0dXJuICp0aGlzOwogIH0KCiAgdGVtcGxhdGUgPHR5cGVuYW1lIEExLCB0eXBlbmFtZSBBMiwgdHlwZW5hbWUgQTM+CiAgTXVsdGlGdW5jT2JqZWN0PFI+IG9wZXJhdG9yICs9KCBSICgqIGYpKEExLCBBMiwgQTMpICkgewogICAgbV9mdW5jc1t0eXBlaWQoIFIoQTEsIEEyLCBBMykgKV0gPSAodm9pZCAoKikoKSkgZjsKICAgIHJldHVybiAqdGhpczsKICB9CgogIFIgb3BlcmF0b3IoKSgpIGNvbnN0CiAgewogICAgdW5vcmRlcmVkX21hcDx0eXBlX2luZGV4LCB2b2lkICgqKSgpPjo6Y29uc3RfaXRlcmF0b3IgaXQgPSBtX2Z1bmNzLmZpbmQodHlwZWlkKCBSKCkgKSk7CiAgICBpZiAoaXQgIT0gbV9mdW5jcy5lbmQoKSkgewogICAgICBSICgqZikoKSA9ICggUiAoKikoKSApKGl0LT5zZWNvbmQpOwogICAgICAoKmYpKCk7CiAgICB9CiAgfQoKICB0ZW1wbGF0ZSA8dHlwZW5hbWUgQTE+CiAgUiBvcGVyYXRvcigpKEExIGExKSBjb25zdAogIHsKICAgIHVub3JkZXJlZF9tYXA8dHlwZV9pbmRleCwgdm9pZCAoKikoKT46OmNvbnN0X2l0ZXJhdG9yIGl0ID0gbV9mdW5jcy5maW5kKHR5cGVpZCggUihBMSkgKSk7CiAgICBpZiAoaXQgIT0gbV9mdW5jcy5lbmQoKSkgewogICAgICBSICgqZikoQTEpID0gKCBSICgqKShBMSkgKShpdC0+c2Vjb25kKTsKICAgICAgKCpmKShhMSk7CiAgICB9CiAgfQoKICB0ZW1wbGF0ZSA8dHlwZW5hbWUgQTEsIHR5cGVuYW1lIEEyPgogIFIgb3BlcmF0b3IoKShBMSBhMSwgQTIgYTIpIGNvbnN0CiAgewogICAgdW5vcmRlcmVkX21hcDx0eXBlX2luZGV4LCB2b2lkICgqKSgpPjo6Y29uc3RfaXRlcmF0b3IgaXQgPSBtX2Z1bmNzLmZpbmQodHlwZWlkKCBSKEExLCBBMikgKSk7CiAgICBpZiAoaXQgIT0gbV9mdW5jcy5lbmQoKSkgewogICAgICBSICgqZikoQTEsIEEyKSA9ICggUiAoKikoQTEsIEEyKSApKGl0LT5zZWNvbmQpOwogICAgICAoKmYpKGExLCBhMik7CiAgICB9CiAgfQoKICB0ZW1wbGF0ZSA8dHlwZW5hbWUgQTEsIHR5cGVuYW1lIEEyLCB0eXBlbmFtZSBBMz4KICBSIG9wZXJhdG9yKCkoQTEgYTEsIEEyIGEyLCBBMyBhMykgY29uc3QKICB7CiAgICB1bm9yZGVyZWRfbWFwPHR5cGVfaW5kZXgsIHZvaWQgKCopKCk+Ojpjb25zdF9pdGVyYXRvciBpdCA9IG1fZnVuY3MuZmluZCh0eXBlaWQoIFIoQTEsIEEyLCBBMykgKSk7CiAgICBpZiAoaXQgIT0gbV9mdW5jcy5lbmQoKSkgewogICAgICBSICgqZikoQTEsIEEyLCBBMykgPSAoIFIgKCopKEExLCBBMiwgQTMpICkoaXQtPnNlY29uZCk7CiAgICAgICgqZikoYTEsIGEyLCBhMyk7CiAgICB9CiAgfQoKfTsKCnZvaWQgXzEoKSB7CiAgY291dCA8PCAiXzEiIDw8IGVuZGw7Cn0KCnZvaWQgXzIoY2hhciB4KSB7CiAgY291dCA8PCAiXzIiIDw8ICIgIiA8PCB4IDw8IGVuZGw7Cn0KCnZvaWQgXzMoaW50IHgpIHsKICBjb3V0IDw8ICJfMyIgPDwgIiAiIDw8IHggPDwgZW5kbDsKfQoKdm9pZCBfNChkb3VibGUgeCkgewogIGNvdXQgPDwgIl80IiA8PCAiICIgPDwgeCA8PCBlbmRsOwp9Cgp2b2lkIF81KGludCBhLCBpbnQgYikgewogIGNvdXQgPDwgIl81IiA8PCAiICIgPDwgYSA8PCAiICIgPDwgYiA8PCBlbmRsOwp9Cgp2b2lkIF82KGNoYXIgYSwgaW50IGIpIHsKICBjb3V0IDw8ICJfNiIgPDwgIiAiIDw8IGEgPDwgIiAiIDw8IGIgPDwgZW5kbDsKfQoKdm9pZCBfNyhpbnQgYSwgaW50IGIsIGludCBjKSB7CiAgY291dCA8PCAiXzciIDw8ICIgIiA8PCBhIDw8ICIgIiA8PCBiIDw8ICIgIiA8PCBjIDw8IGVuZGw7Cn0KCmludCBtYWluKCkgewogIE11bHRpRnVuY09iamVjdDx2b2lkPiBmdW5jczsKICBmdW5jcyArPSAmXzE7CiAgZnVuY3MgKz0gJl8yOwogIGZ1bmNzICs9ICZfMzsKICBmdW5jcyArPSAmXzQ7CiAgZnVuY3MgKz0gJl81OwogIGZ1bmNzICs9ICZfNjsKICBmdW5jcyArPSAmXzc7CiAgZnVuY3MoKTsKICBmdW5jcygnYScpOwogIGZ1bmNzKDU2KTsKICBmdW5jcyg1LjUpOwogIGZ1bmNzKDIsIDUpOwogIGZ1bmNzKCdxJywgNik7CiAgZnVuY3MoMSwgMiwgMyk7CiAgcmV0dXJuIDA7Cn0KCg==