// generics are compiled per set of type arguments: T can be any size, new(T) // stamps the real type, and a struct can take several parameters struct pt { int x, y; }; struct record { K key; V val; }; struct box { int n; T* items; }; K rkey(record* r) { return r.key; } V* rval(record* r) { return &r.val; } int tsize() { return sizeof(T); } T*.u make(int n) { T* p = new(T, n) as T*; return u*p; } record*.u mkrec(K k) { record* r = new(record); r.key = k; return u*r; } T pick(T* a, int i) { return a[i]; } int sumn(T* a, int n) { int s = 0; for (int i = 0; i < n; i++) s += a[i]; return s; } fn nameof() { return tname(typeof(T)); } o3 int osum(T* a, int n) { int s = 0; for (int i = 0; i < n; i++) s += a[i].x + a[i].y; return s; } int depth(int n) { if (n == 0) return tsize(); return depth(n - 1); } int main() { record* a = mkrec(9); a.val.x = 5; a.val.y = 6; put_n(rkey(a)); put_c(' '); put_n(rval(a).y); put_c(' '); put_n(sizeof(record)); put_c(' '); put_n(tsize()); put_c(' '); put_n(tsize()); put_c(' '); put_n(tsize>()); put_c(' '); put_n(depth(5)); put_c(10); pt* ps = make(3); ps[2].x = 40; ps[2].y = 2; put_n(pick(ps, 2).x + ps[2].y); put_c(' '); put_s(nameof()); put_c(' '); put_s(nameof()); put_c(' '); put_n(osum(ps, 3)); put_c(' '); int* is = make(4); is[0] = 1; is[1] = 2; is[2] = 3; is[3] = 4; put_n(sumn(is, 4)); put_c(' '); record* b = mkrec(ps); put_n(b.key == ps); put_c(10); free(d*a); free(d*b); free(d*ps); free(d*is); return 0; }