#include <iostream>

template <typename T>
struct id {
	using type = T;
};


template <typename T>
struct force_match : T {};

template <typename T>
struct force : force_match<typename T::type> {};

template <template <typename...> class T, typename... Args>
struct force_match<T<Args...>> : T<typename force<Args>::type...> {};


template <int N>
struct int_ : id<int_<N>> {
	static constexpr int value = N;
};

template <typename A, typename B>
struct plus_match {};

template <typename A, typename B>
struct plus : plus_match<typename A::type, typename B::type> {};

template <int A, int B>
struct plus_match<int_<A>, int_<B>> : int_<A + B> {};


template <typename A, typename B>
struct minus_match {};

template <typename A, typename B>
struct minus : minus_match<typename A::type, typename B::type> {};

template <int A, int B>
struct minus_match<int_<A>, int_<B>> : int_<A - B> {};


template <typename A, typename B>
struct mul_match {};

template <typename A, typename B>
struct mul : mul_match<typename A::type, typename B::type> {};

template <int A, int B>
struct mul_match<int_<A>, int_<B>> : int_<A * B> {};


template <typename N>
struct dec : minus<N, int_<1>> {};


template <bool B>
struct bool_ : id<bool_<B>> {
	static constexpr bool value = B;
};


using true_ = bool_<true>;
using false_ = bool_<false>;


template <typename A, typename B>
struct eq_match : false_ {};

template <typename A, typename B>
struct eq : eq_match<typename A::type, typename B::type> {};

template <typename T>
struct eq_match<T, T> : true_ {};


template <typename Cond, typename Then, typename Else>
struct if_match {};

template <typename Cond, typename Then, typename Else>
struct if_ : if_match<typename Cond::type, Then, Else> {};

template <typename Then, typename Else>
struct if_match<true_, Then, Else> : Then::type {};

template <typename Then, typename Else>
struct if_match<false_, Then, Else> : Else::type {};



template <typename N>
struct factorial : if_< eq<N, int_<0>>
                      , int_<1>
                      , mul<N, factorial<dec<N>>>> {};


int main() {
	
	std::cout << force< factorial<int_<4>> >::type::value << std::endl;
	
	std::cout << force< factorial<int_<-3>> >::value << std::endl;
	
	return 0;
}
