#include <iostream>
#include <vector>

typedef std::vector<unsigned> arguments;
typedef unsigned nat;

template<typename F, typename... G>
struct S {

	static nat apply(arguments const & args) {
		arguments output = { G::apply(args)... };
		return F::apply(output);
	}

	template<typename... T>
	static nat apl(T... x) {
		arguments args = { static_cast<nat>(x)... };
		return apply(args);
	}
};

template<nat N, nat M>
struct U {

	static nat apply(arguments const & args) {
		return args[M - 1];
	}

	template<typename... T>
	static nat apl(T... x) {
		arguments args = { static_cast<nat>(x)... };
		return apply(args);
	}
};

struct N {

    static nat apply(arguments const & v) {
        return v[0] + 1;
    }

    template<typename... T>
    static nat apl(T... x) {
    	arguments args = { static_cast<nat>(x)... };
        return apply(args);
    }
};

int main() {
	std::cout << S<N, U<2, 1> >::apl(5, 3) << std::endl;
	return 0;
}