I’m running across a very annoying problem regarding transitive const in D.
I have the code below:
struct Slice(T)
{
T items;
size_t start, length, stride;
this(T items, size_t start = 0, size_t length = size_t.max, size_t stride=1)
{
if (length == size_t.max)
{ length = 1 + (items.length - start - 1) / stride; }
this.items = items;
this.start = start;
this.length = length;
this.stride = stride;
}
Slice!(T) opSlice(size_t a, size_t b)
{
// Everything is fine here
return Slice!(T)(items, start + a * stride, b - a, stride);
}
const(Slice!(T)) opSlice(size_t a, size_t b) const
{
// ERROR! 'items' is const(T), not T.
return const(Slice!(T))(items, start + a * stride, b - a, stride);
}
}
The trouble I’m running to is that, pretty much, the data types const(Slice!int) and Slice!const(int) and const(Slice!const(int)) are just… weird.
How do I overload opSlice above, to return a constant copy of the current slice which can subsequently be used like the original slice?
In other words, let’s say I have:
void test(in Slice!(int[]) some_slice)
{
//...
}
void main()
{
auto my_slice = Slice!(int[])();
const my_const_slice = my_slice;
test(my_slice); // succeeds
test(my_const_slice); //succeeds
test(my_const_slice[0 .. 1]); // fails
}
The code above doesn’t work. What is the best way of making it work? (I could of course always templatize test(), but then all the slice variations — const(Slice!(Slice!const(int[]))) and such — would grow exponentially, and confusingly so.)
Edit:
Is there a solution that works for structs and classes?
inout also works if Slice is a class: