D中恼人的,传递性的问题

Meh*_*dad 6 d 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我跑的麻烦是,相当多的数据类型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
}
Run Code Online (Sandbox Code Playgroud)

上面的代码不起作用.使它工作的最佳方法是什么?(我当然可以总是模板化test(),但是然后所有的切片变化 - const(Slice!(Slice!const(int[])))等等 - 都会成倍增长,而且容易引起混淆.)

编辑:

有适用于structs class es 的解决方案吗?

rat*_*eak 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;
}
Run Code Online (Sandbox Code Playgroud)

inout为此创建了关键字,它允许参数的const-ness/immutability传播到结果


小智 3

如果 Slice 是一个类,则 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
}
Run Code Online (Sandbox Code Playgroud)