Я столкнулся с очень раздражающей проблемой относительно переходного const в D.
У меня есть код ниже:
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);
}
}
Проблема, с которой я столкнулся, заключается в том, что, в основном, типы данных const(Slice!int)
и Slice!const(int)
и const(Slice!const(int))
просто... weird.
Как мне перегрузить opSlice
выше, чтобы вернуть константную копию текущего среза, которая впоследствии может быть использована как оригинальный срез?
Другими словами, допустим, у меня есть:
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
}
Код выше не работает. Какой лучший способ заставить его работать? (Конечно, я мог бы всегда шаблонизировать test()
, но тогда все вариации срезов - const(Slice!(Slice!const(int[])))
и тому подобное - будут расти экспоненциально, и это запутает)
Есть ли решение, которое работает для struct
s и class
es?