December 27, 2012
In some situations I need to pass to a function a "nullable" fixed sized array. This happens if you use fixed-sized arrays a lot. So:
- You can't use ref, because it can't be null.
- Passing to the function a raw pointer and then using it as  (*arr)[x]  doesn't look nice.
- NullableRef is a solutions, but it contain enforces that kill inlining and make the code slower, so it's not usable for performance-sensitive code (unless you turn the nullable into a regular pointer inside the function, but this makes using NullableRef much less useful).

This solution is derived by NullableRef:


struct Ptr(T) {
    private T* ptr;

    this(T* ptr_) pure nothrow {
        this.ptr = ptr_;
    }

    bool opCast(T)() const pure nothrow if (is(T == bool)) {
        return ptr !is null;
    }

    @property ref inout(T) get()() inout pure nothrow
    in {
        assert(ptr);
    } body {
        return *ptr;
    }

    alias get this;
}

Ptr!T ptr(T)(ref T x) {
    return typeof(return)(&x);
}

// Example usage ---------------------------------------

alias TA = immutable(int[5]);

bool foo(Ptr!TA arr=Ptr!TA.init) nothrow {
    if (arr)
        return arr[1] == 20;
    else
        return false;
}

bool foo(typeof(null) _) nothrow {
    return false;
}

void main() {
    assert(!foo());
    assert(!foo(null));
    TA items = [10, 20, 30, 40, 50];
    assert(foo(ptr(items)));
}


The usage in foo() is clean.

I've created a kind of benchmark and unfortunately I've seen that with DMD (compiling with -O -release -inline -noboundscheck) this very light wrapping is not as efficient as a pointer to fixed-sized array :-(
(But it's better than NullableRef).

Bye,
bearophile