static class C { int i; void f() { i = 3; } }
static struct S { int i; void f() { i = 3; } }
void f0(NotNull!C c) {
c.f();
}
void f1(NotNull!(S*) sp) {
sp.f();
}
auto c = notNull!C;
auto sp = notNull!(S*);
f0(c);
f1(sp);
assert(c.i == 3);
assert(sp.i == 3);
A NotNull type ensure that the type you give it can never have a null value. So it is always safe to use. It's specifically designed for pointers to values or classes. You can give it a struct as well.
The one thing to watch out for is inner classes or structs. Since notNull is a template function, and it ensures that a type T is always created, it has to allocate memory. But inner classes and structs need a context pointer to be newed, so this only works with static inner classes and structs.
the constructor is disabled, so you have to use the function notNull to construct NotNull objects.