#include <iostream>
using namespace std;

typedef int (*ptr1)(int, int);
int add1(int a, int b){return a+b;}

typedef double (*ptr2)(double, double, double);
double add2(double a, double b, double c){return a+b+c;}

template <typename TResult>
class executor{
    class executable;
    
    template<typename T1, typename T2, typename Func>
    class _e2;
public:
    template <typename T1, typename T2, typename Func>
    executor(T1 arg1, T2 arg2, Func f) : e(new _e2<T1,T2,Func>(arg1, arg2, f)){}
    
    template <typename T1, typename T2, typename T3, typename Func>
    executor(T1 arg1, T2 arg2, T3 arg3, Func f) : e(new _e3<T1,T2,T3,Func>(arg1, arg2, arg3, f)){}
    
    
    TResult execute() {return e->execute();}
private:
    executable *e;
private:
    class executable{
    public:
        virtual TResult execute() = 0;
    };
    
    template<typename T1, typename T2, typename Func>
    class _e2 : public executable{
    public:
        _e2(T1 arg1, T2 arg2, Func f) : _arg1(arg1), _arg2(arg2), _f(f) {}
    public:
        TResult execute() {return _f(_arg1, _arg2);}
    private:
        T1 _arg1;
        T2 _arg2;
        Func _f;
    };
    
    template<typename T1, typename T2, typename T3, typename Func>
    class _e3 : public executable{
    public:
        _e3(T1 arg1, T2 arg2, T3 arg3, Func f) : _arg1(arg1), _arg2(arg2), _arg3(arg3), _f(f) {}
    public:
        TResult execute() {return _f(_arg1, _arg2, _arg3);}
    private:
        T1 _arg1;
        T2 _arg2;
        T3 _arg3;
        Func _f;
    };
};


int main()
{
    executor<int> etor(1, 1, add1);
    cout << etor.execute() << endl;
    
    executor<double> etor2(1.0, 1.0, 1.0, add2);
    cout << etor2.execute() << endl;
    
    return 0;
}
