Thread overview
opIndex operators
Apr 13, 2013
gedaiu
Apr 13, 2013
bearophile
Apr 13, 2013
gedaiu
Apr 13, 2013
bearophile
Apr 14, 2013
gedaiu
Apr 14, 2013
bearophile
Apr 14, 2013
Jesse Phillips
April 13, 2013
Hi again!

I don't understand why we have opIndex() and opIndexAssign()... can anyone explain this for me?

Because in c++ there is only one operator overload for "[]" and it looks like this:

Value& Value::operator[] (constValue offset) {
	return container[offset];
}

and with this operator overload I can set or get values from container, and also easily implement custom multilevel arrays.

In D when I have this method

Value& opIndex(Value index) {
	return container[index];
}

I get this error.

Error: no identifier for declarator Value
Error: semicolon expected, not '&'
Declaration expected, not '&'

And also, how you can implement custom structs that acts like a multilevel array in D like in c++?

Thanks!
April 13, 2013
On Saturday, 13 April 2013 at 09:53:01 UTC, gedaiu wrote:
> Hi again!
>
> I don't understand why we have opIndex() and opIndexAssign()... can anyone explain this for me?

opIndex returns the value contained in the "array", while opIndexAssign does the opposite, it puts in your "array" the given value. If you use opIndex and return the item by reference you sometimes don't need opIndexAssign. But for other cases you need both.

Info on D operator overloading:
http://dlang.org/operatoroverloading.html


> In D when I have this method
>
> Value& opIndex(Value index) {
> 	return container[index];
> }
>
> I get this error.
>
> Error: no identifier for declarator Value
> Error: semicolon expected, not '&'
> Declaration expected, not '&'

In D there isn't that & syntax. We have "ref". But it's not usable in all the situations where you use & in C++.


> And also, how you can implement custom structs that acts like a multilevel array in D like in c++?

By multi-level array I think you mean something like a matrix:


import std.stdio;

struct Foo {
    float[] mat;
    size_t nCols;

    this(in size_t r, in size_t c) pure nothrow
    in { // pre-condition
        assert(r > 0);
        assert(c > 0);
    } body {
        nCols = c;
        mat.length = r * c; // All NaN.
    }

    float opIndex(in size_t r, in size_t c) pure nothrow {
        return mat[r * nCols + c];
    }

    float opIndexAssign(in float value, in size_t r, in size_t c)
    pure nothrow {
        mat[r * nCols + c] = value;
        return value;
    }
}

void main() {
    auto m = Foo(3, 5);
    m[1, 3] = 5.5;
    m[1, 3].writeln;
    m.mat.writeln;
}



An alternative design is to use ref. Here it can be used:


import std.stdio;

struct Foo {
    float[] mat;
    size_t nCols;

    this(in size_t r, in size_t c) pure nothrow
    in {
        assert(r > 0);
        assert(c > 0);
    } body {
        nCols = c;
        mat.length = r * c; // All NaN.
    }

    ref float opIndex(in size_t r, in size_t c) pure nothrow {
        return mat[r * nCols + c];
    }
}

void main() {
    auto m = Foo(3, 5);
    m[1, 3] = 5.5;
    m[1, 3].writeln;
    m.mat.writeln;
}


Bye,
bearophile
April 13, 2013
Hi,

thanks for the answer, but it's not the solution what i was expectig. What i want to create, is an array structure like the one from PHP where array levels are not fixed and the sintax to access rhe values is val[][] so returning a reference to a struct that have the same type as the current type is useful.

there is a way to do this in D?

thanks!
April 13, 2013
gedaiu:

> What i want to create, is an array structure like the one from PHP where array levels are not fixed and the sintax to access rhe values is val[][] so returning a reference to a struct that have the same type as the current type is useful.
>
> there is a way to do this in D?

Instead of returning float as in my case, you return something else that has opIndex and opIndexAssign. This way you can pile up the []:


import std.stdio;

struct Foo {
    ref Foo opIndex(in size_t i) {
        writeln("opIndex: ", i);
        return this;
    }

    void opIndexAssign(in float value, in size_t i) {
        writeln("opIndexAssign: ", value, " ", i);
    }
}

void main() {
    Foo f;
    f[1] = 2;
    f[3][4] = 5;
    f[6][7][8] = 9;
}


That outputs:

opIndexAssign: 2 1
opIndex: 3
opIndexAssign: 5 4
opIndex: 6
opIndex: 7
opIndexAssign: 9 8

Bye,
bearophile
April 14, 2013
On Saturday, 13 April 2013 at 11:41:02 UTC, bearophile wrote:
> gedaiu:
>
>> What i want to create, is an array structure like the one from PHP where array levels are not fixed and the sintax to access rhe values is val[][] so returning a reference to a struct that have the same type as the current type is useful.
>>
>> there is a way to do this in D?
>
> Instead of returning float as in my case, you return something else that has opIndex and opIndexAssign. This way you can pile up the []:
>
>
> import std.stdio;
>
> struct Foo {
>     ref Foo opIndex(in size_t i) {
>         writeln("opIndex: ", i);
>         return this;
>     }
>
>     void opIndexAssign(in float value, in size_t i) {
>         writeln("opIndexAssign: ", value, " ", i);
>     }
> }
>
> void main() {
>     Foo f;
>     f[1] = 2;
>     f[3][4] = 5;
>     f[6][7][8] = 9;
> }
>
>
> That outputs:
>
> opIndexAssign: 2 1
> opIndex: 3
> opIndexAssign: 5 4
> opIndex: 6
> opIndex: 7
> opIndexAssign: 9 8
>
> Bye,
> bearophile


Value[Value] container;

ref Value opIndex(Value index) {
	return container[index];
}

why I get this error?

Error: function base.Value.Value.opIndex (Value index) is not callable using argument types (string)
Error: cannot implicitly convert expression ("string") of type string to Value

I have implemented this methods:
this(string)
Value opCast(string val)
Value opAssign(ref const string val)

Thanks!




April 14, 2013
gedaiu:

> Value[Value] container;
>
> ref Value opIndex(Value index) {
> 	return container[index];
> }
>
> why I get this error?
>
> Error: function base.Value.Value.opIndex (Value index) is not callable using argument types (string)
> Error: cannot implicitly convert expression ("string") of type string to Value
>
> I have implemented this methods:
> this(string)
> Value opCast(string val)
> Value opAssign(ref const string val)

When possible it's better to show the actual code, and double-bonus if it's complete and compilable (or supposed to be compilable).

Bye,
bearophile
April 14, 2013
On Sunday, 14 April 2013 at 06:57:34 UTC, gedaiu wrote:
> Error: function base.Value.Value.opIndex (Value index) is not callable using argument types (string)
> Error: cannot implicitly convert expression ("string") of type string to Value
>
> I have implemented this methods:
> this(string)
> Value opCast(string val)
> Value opAssign(ref const string val)

void foo(Value v);

foo("my value?");

This code does not compile unless Value is defined as

alias Value = string;

You'd call it:

foo(Value("my value"));