Well, if you can use RTTI, you can define a MultiFuncObject like this, and you can easily link other functions. In addition, they can be easily called. But unfortunately, this approach only works for a limited number of arguments. But in fact, boost::bind also supports a limited number of arguments (9 by default). In this way, you can expand this class to suit your needs.
Before giving you the source of MultiFuncObject , I want to show you how you can use it. It takes a template argument, which will be used as the return type. You can associate new functions with the += operator. Using some template magic, a class distinguishes differences between related functions with the same number of arguments with at least one other type of argument.
You need C ++ 11 because MultiFuncObject uses std::unordered_map and std::type_index .
Here is the usage:
#include <iostream> using namespace std; 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; }
I hope this is close to what you want. Here is the source of MultiFuncObject :
#include <typeinfo> #include <typeindex> #include <unordered_map> 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); } } };
It stores prototypes of various functions using std::unordered_map with std::type_index and void (*)() values. If necessary, the correct function is extracted using this card.
Here is a working example