www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - opIndex operators

reply "gedaiu" <szabobogdan yahoo.com> writes:
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!
Apr 13 2013
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
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
Apr 13 2013
parent reply "gedaiu" <szabobogdan yahoo.com> writes:
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!
Apr 13 2013
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
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
Apr 13 2013
parent reply "gedaiu" <szabobogdan yahoo.com> writes:
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!
Apr 13 2013
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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
Apr 14 2013
prev sibling parent "Jesse Phillips" <Jessekphillips+d gmail.com> writes:
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"));
Apr 14 2013