On Wednesday, 27 May 2015 at 14:12:02 UTC, Martin Nowak wrote:
On Sunday, 24 May 2015 at 15:13:41 UTC, Vladimir Panteleev wrote:
Could you elaborate on what these magic semantics are?

and no easy solution exists for the ++aa[key1][key2] case.

Is this specific to the pre-increment? aa[key1][key2]++ is generally a useful pattern.

This applies to pre/post increment as well as assignment and opOpAssign. When an lvalue is needed the compiler will call a special runtime function GetX to obtain an lvalue for aa[key1], i.e. the entry will be default initialized iff missing. If the expression is an rvalue though (aa[key1][key2]), a missing key1 will trigger a range error. In an opIndex(Key) you have no idea whether the whole expression I an lvalue or an rvalue.

IIRC the construction/assignment of a value is also handled specifically.

BTW, may be we should create DIP about opIndex extending?
What do you want about following?
Let, if opIndex is template, and the first template argument is a bool value, compiler should pass true, if this is a part of l-value expression:

struct Foo
{
    Foo[] children;
    this(int value)
    {
        this.value = value;
    }
    int value;

    ref Foo opIndex(bool lvl)(size_t idx)
    {
        if (idx < children.length)
            return children[idx];
        static if (lvl)
        {
            children.length = idx + 1;
            return children[idx];
        }
        else
        {
            throw new Exception("out of bounds");
        }
    }
}


Foo f;
f[5][3] = Foo(42); translates to
    f.opIndex!(true)(5).opIndex!(true)(3) = Foo(42);

auto x = f[5][4]; translates to
    auto x = f.opIndex!(false)(5).opIndex!(false)(3);

Reply via email to