#include <iostream>
#define TMPL_EXPAND(T) TMPL_CALL(TMPL_EXPAND_ ## T TMPL_E)
#define TMPL_CALL(T) T
#define TMPL_CALL_EXPAND TMPL_EXPAND2
#define TMPL_EXPAND2(T) TMPL_CALL2(TMPL_EXPAND2_ ## T TMPL_E)
#define TMPL_CALL2(T) T
#define TMPL_CALL_EXPAND2 TMPL_EXPAND3
#define TMPL_EXPAND3(T) TMPL_CALL3(TMPL_EXPAND3_ ## T TMPL_E)
#define TMPL_CALL3(T) T
#define TMPL_CALL_EXPAND3 TMPL_EXPAND4
#define TMPL_EXPAND4(T) TMPL_CALL4(TMPL_EXPAND3_ ## T TMPL_E)
#define TMPL_CALL4(T) T
#define TMPL_O (
#define TMPL_E )
#define TMPL_EXPAND_stop_now typename = void(
#define TMPL_EXPAND_T typename T , TMPL_CALL_EXPAND TMPL_O
#define TMPL_EXPAND_T1 typename T1, TMPL_CALL_EXPAND TMPL_O
#define TMPL_EXPAND_T2 typename T2, TMPL_CALL_EXPAND TMPL_O
#define TMPL_EXPAND_U typename U , TMPL_CALL_EXPAND TMPL_O
#define TMPL_EXPAND_S typename S , TMPL_CALL_EXPAND TMPL_O
#define TMPL_EXPAND_int_I int I , TMPL_CALL_EXPAND TMPL_O
#define TMPL_EXPAND2_stop_now typename = void(
#define TMPL_EXPAND2_T typename T , TMPL_CALL_EXPAND2 TMPL_O
#define TMPL_EXPAND2_T1 typename T1, TMPL_CALL_EXPAND2 TMPL_O
#define TMPL_EXPAND2_T2 typename T2, TMPL_CALL_EXPAND2 TMPL_O
#define TMPL_EXPAND2_U typename U , TMPL_CALL_EXPAND2 TMPL_O
#define TMPL_EXPAND2_S typename S , TMPL_CALL_EXPAND2 TMPL_O
#define TMPL_EXPAND2_int_I int I , TMPL_CALL_EXPAND2 TMPL_O
#define TMPL_EXPAND3_stop_now typename = void(
#define TMPL_EXPAND3_T typename T , TMPL_CALL_EXPAND3 TMPL_O
#define TMPL_EXPAND3_T1 typename T1, TMPL_CALL_EXPAND3 TMPL_O
#define TMPL_EXPAND3_T2 typename T2, TMPL_CALL_EXPAND3 TMPL_O
#define TMPL_EXPAND3_U typename U , TMPL_CALL_EXPAND3 TMPL_O
#define TMPL_EXPAND3_S typename S , TMPL_CALL_EXPAND3 TMPL_O
#define TMPL_EXPAND3_int_I int I , TMPL_CALL_EXPAND3 TMPL_O
#define TMPL(T) template < TMPL_EXPAND(T stop_now) >
TMPL(int_I)
int int_id() { return I; }
TMPL(T)
T default_value() { return T{}; }
TMPL(T S U)
T sum(S const& s, U const& u) { return s+u; }
int main()
{
std::cout << int_id<3>() << '\n';
std::cout << default_value<double>() << '\n';
std::cout << sum<long double>(1.0, 2.1f) << '\n';
}