Comment #0 by bearophile_hugs — 2013-01-03T05:25:28Z
When I use fixed-sized arrays a lot, sometimes I need a nullable version of them (fixed-sized arrays are allocated in-place, so they often avoid heap allocations, avoiding the creation of some garbage, reducing the GC pressure and generally speeding up the code). A "ref" can't be used because it can't be null.
So I think the normal way to use them in D is this, but the "(*arr)[1]" syntax is bug-prone and not elegant:
alias TA = immutable(int[5]);
bool foo(TA* arr) {
if (arr)
return (*arr)[1] == 20;
else
return false;
}
void main() {
TA a;
foo(&a);
}
std.typecons.Nullable and std.typecons.NullableRef contain enforce() that throws and kills inlining.
This simple struct inspired by NullableRef is light, avoids the problem of NullableRef and allows for a natural syntax for nullable fixed sized arrays:
// Nullable fixed-sized array --------
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)));
}
//---------------------------------
Unfortunately my benchmarks show that with the current DMD 2.061 the code that uses such wrapped array is not as efficient as the first program that uses the pointer to the fixed sized array.
Comment #1 by monarchdodra — 2013-02-04T22:57:48Z
(In reply to comment #0)
> std.typecons.Nullable and std.typecons.NullableRef contain enforce() that
> throws and kills inlining.
FYI: I submitted a pull that changes those enforces to logic errors (asserts):
https://github.com/D-Programming-Language/phobos/pull/1103
This should allow the code to inline.
Comment #2 by github-bugzilla — 2013-03-02T10:06:08Z
Comment #5 by bearophile_hugs — 2013-03-02T13:42:02Z
Using the updated NullableRef in my code I've seen that it is good enough for the purposes explained here, so I close down this issue.
I'd like a more handy way to create a nullable, like:
Ptr!T ptr(T)(ref T x) {
return typeof(return)(&x);
}
So I've created the Issue 9637