import std.stdio; struct Empty {} template TupleType(A = Empty, B = Empty, C = Empty, D = Empty, E = Empty, F = Empty, G = Empty /*,...*/) { static if (is(A == Empty)) alias Empty TupleType; else alias List!(A,.TupleType!(B,C,D,E,F,G/*,...*/)) TupleType; } template Tuple(A = Empty, B = Empty, C = Empty, D = Empty, E = Empty, F = Empty, G = Empty /*,...*/) { TupleType!(A,B,C,D,E,F,G /*,...*/) Tuple(A a = A.init, B b = B.init, C c = C.init, D d = D.init, E e = E.init, F f = F.init, G g = G.init /*,...*/) { static if (is(A == Empty)) return Empty.init; else return List!(A,TupleType!(B,C,D,E,F,G/*,...*/))(a,.Tuple(b,c,d,e,f,g /*,...*/)); } } struct List(A,B) { A head; B tail; static List opCall(A a, B b) { List!(A,B) ret; ret.head = a; ret.tail = b; return ret; } } template decl_vararg_func(alias realFunc) { template func(A = Empty, B = Empty, C = Empty, D = Empty, E = Empty, F = Empty, G = Empty /*, ...*/) { static void func(A a = A.init, B b = B.init, C c = C.init, D d = D.init, E e = E.init, F f = F.init, G g = G.init /*,...*/) { realFunc(Tuple(a,b,c,d,e,f,g /*,...*/)); } } } template funcImpl(T) { void funcImpl(T args) { static if (is(T == Empty)) { writefln("Done!"); } else { writefln("Got argument: (%s) %s",typeid(typeof(args.head)),args.head); .funcImpl(args.tail); } } } struct dummy1 { mixin decl_vararg_func!(funcImpl); } alias dummy1.func func; template funcImpl2(T) { void funcImpl2(T args, int n = 0) { static if (is(T == Empty)) { writefln("funcImpl2 called with %s argument(s)",n); } else { .funcImpl2(args.tail, n+1); } } } struct dummy2 { mixin decl_vararg_func!(funcImpl2); } alias dummy2.func func2; void main() { int a = 1; float b = 5.6; long c = 3; char[] d = "test"; func(a,b,c,d); func2(a,b,c,d); func2(); }