我遇到了关于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))
只是...... 怪异。
如何重载上面的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
的解决方案?
答案 0 :(得分:5)
将构造函数更改为
inout this(inout 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;
}
为此创建了inout
关键字,它允许参数的const-ness / immutability传播到结果
答案 1 :(得分:3)
inout也有效:
class Slice(T)
{
T items;
size_t start, length, stride;
this(){}
inout this(inout 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;
}
inout(Slice!(T)) opSlice(size_t a, size_t b) inout{
return new inout(Slice!T)(items, start + a * stride, b - a, stride);
}
}
void test(in Slice!(int[]) some_slice)
{
//...
}
void main()
{
auto my_slice = new Slice!(int[])();
const my_const_slice = my_slice;
test(my_slice); // succeeds
test(my_const_slice);//succeeds
test(my_const_slice[0 .. 1]); // succeeds
}