void foo(int *) {} void bar(void *) {} forall(otype T) void baz(T *); forall(dtype T) void qux(T *); forall(dtype T | sized(T)) void quux(T *); struct A; // incomplete struct B {}; // complete int main() { int *i; void *v; // A * x; // A * y; // B * x; // B * z; // okay *i; // *x; // picks B // *z; foo(i); bar(i); baz(i); qux(i); quux(i); bar(v); qux(v); foo(v); // questionable, but works at the moment for C compatibility // bad *v; // *y; baz(v); quux(v); } forall(otype T) void baz(T * x) { // okay bar(x); baz(x); qux(x); quux(x); *x; } forall(dtype T) void qux(T * y) { // okay bar(y); qux(y); // bad baz(y); quux(y); *y; } forall(dtype T | sized(T)) void quux(T * z) { // okay bar(z); qux(z); quux(z); *z; // bad baz(z); }