size_t getindex(A,T)(ref A a,ref T t){
auto p1=&a[0];
auto p2=&t;
if(p1>p2 || p2>&a[$-1]){return size_t.max;}
return p2-p1;
}
unittest{
// fixed array
int[5] arr=[10,20,30,40,50];
assert(arr.getindex(arr[0])==0);
assert(arr.getindex(arr[2])==2);
assert(arr.getindex(arr[4])==4);
// out of bounds — element not in array
int outside=99;
assert(arr.getindex(outside)==size_t.max);
// slice
int[] s=arr[];
assert(s.getindex(s[1])==1);
assert(s.getindex(s[3])==3);
int outsideSlice=99;
assert(s.getindex(outsideSlice)==size_t.max);
struct naive(T,int N){
T[N] data;
int length;
ref T opIndex(int i)=>data[i];
int opDollar()=>length;
void opOpAssign(string s:"~")(T a){
data[length++]=a;
}
}
// naive via generic overload
naive!(int,10) d;
d~=11;
d~=22;
d~=33;
assert(d.getindex(d[0])==0);
assert(d.getindex(d[1])==1);
assert(d.getindex(d[2])==2);
naive!(int,10) other;
other~=11;
assert(d.getindex(other[0])==size_t.max);
}
One of the fundamentally incorrect alternatives indexOf, it should not be called the mythical indexOf but it has different tradeoffs from countUntil, for continuous data and your maintaining ref it can work
For the safety you probaly want these asserts/contracts:
a[1]-a[0]==t.sizeof
if(a.length compiles) a[$-1]-a[0]==t.sizeof*a.length
typeof(a[0])==T
I think given those asserts it would just be as safe as slices/ std.find
One of the fundamentally incorrect alternatives indexOf, it should not be called the mythical indexOf but it has different tradeoffs from countUntil, for continuous data and your maintaining ref it can work
For the safety you probaly want these asserts/contracts:
a[1]-a[0]==t.sizeofif(a.length compiles) a[$-1]-a[0]==t.sizeof*a.lengthtypeof(a[0])==TI think given those asserts it would just be as safe as slices/ std.find