Consider the following example:

module demo1;

```D
class MyClass
{
    int a;

    this(int a)
    {
        this.a = a;
    }
}

struct MyRange
{
    MyClass[] _items;

    this(MyClass[] items)
    {
        this._items = items;
    }

    int opApply(scope int delegate(inout MyClass item) dg) inout
    {
        for (size_t i = 0; i < this._items.length; i++)
        {
            int result = dg(this._items[i]);
            if (result != 0)
            {
                return result;
            }
        }
        return 0;
    }

    inout(MyClass) opIndex(size_t i) inout nothrow
    {
        return this._items[i];
    }

    size_t length() const nothrow
    {
        return this._items.length;
    }

    public alias opDollar = length;
}

void main()
{
    MyClass[2] items;
    items[0] = new MyClass(1);
    items[1] = new MyClass(2);

    MyRange r = MyRange(items);

    foreach (MyClass item; r)
    {
        // Operations
    }

    const MyRange r2 = MyRange(items);

    foreach (const MyClass item; r2)
    {
        // Operations
    }
}
```

The idea is that when the range is constant looping should yield constant objects and when it's mutable it should yield mutable objects.

The code above leads to the following error:

```
Error: cannot uniquely infer `foreach` argument types
    foreach (MyClass item; r)
Error: cannot uniquely infer `foreach` argument types
    foreach (const MyClass item; r2)
```

This problem does not occur if I replace the `inout` declaration of `opApply` with the following:

```D
int opApply(scope int delegate(MyClass item) dg)
{
    for (size_t i = 0; i < this._items.length; i++)
    {
        int result = dg(this._items[i]);
        if (result != 0)
        {
            return result;
        }
    }
    return 0;
}

int opApply(scope int delegate(const MyClass item) dg) const
{
    for (size_t i = 0; i < this._items.length; i++)
    {
        int result = dg(this._items[i]);
        if (result != 0)
        {
            return result;
        }
    }
    return 0;
}
```

This is obviously suboptimal and requires duplication of code.

Is there a way to obtain the desired effect without duplicating code?

Thank you a lot in advance!

Reply via email to