Thread overview |
---|
July 06, 2015 Array operations with array of structs | ||||
---|---|---|---|---|
| ||||
Hi, I have a struct with arithmetic operations defined using opBinary but array operations with arrays of it don't work. struct Vector3 { public double[3] _p; ... Vector3 opBinary(string op)(in Vector3 rhs) const if (op == "+"){ Vector3 result; result._p[] = this._p[] + rhs._p[]; return result; } ... } unittest{ auto a = Vector3([2.0, 2.0, 0.0]); auto b = Vector3([1.0, 2.0, 1.0]); Vector3[] c = [a]; Vector3[] d = [b]; Vector3 e = a + b; // works Vector3[] f; f[] = c[] + d[]; // Error: invalid array operation 'f[] = c[] + d[]' because Vector3 doesn't support necessary arithmetic operations } how can I get this to work? Thanks |
July 06, 2015 Re: Array operations with array of structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Peter | On Monday, 6 July 2015 at 01:16:54 UTC, Peter wrote:
> Hi,
> I have a struct with arithmetic operations defined using opBinary but array operations with arrays of it don't work.
>
> struct Vector3 {
> public double[3] _p;
> ...
> Vector3 opBinary(string op)(in Vector3 rhs) const
> if (op == "+"){
> Vector3 result;
> result._p[] = this._p[] + rhs._p[];
> return result;
> }
> ...
> }
>
> unittest{
> auto a = Vector3([2.0, 2.0, 0.0]);
> auto b = Vector3([1.0, 2.0, 1.0]);
> Vector3[] c = [a];
> Vector3[] d = [b];
> Vector3 e = a + b; // works
> Vector3[] f;
> f[] = c[] + d[]; // Error: invalid array operation 'f[] = c[] + d[]' because Vector3 doesn't support necessary arithmetic operations
> }
>
> how can I get this to work?
>
> Thanks
you need to define the slice operators. e.g.
auto opSlice() // no parameters to get whole slice eg. a[]
// can also define with opSlice(size_t i, size_t j)
// for access like a[ i .. j]
{
return _p;
}
|
July 06, 2015 Re: Array operations with array of structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nicholas Wilson | On Monday, 6 July 2015 at 03:02:59 UTC, Nicholas Wilson wrote: > On Monday, 6 July 2015 at 01:16:54 UTC, Peter wrote: >> Hi, >> I have a struct with arithmetic operations defined using opBinary but array operations with arrays of it don't work. >> >> struct Vector3 { >> public double[3] _p; >> ... >> Vector3 opBinary(string op)(in Vector3 rhs) const >> if (op == "+"){ >> Vector3 result; >> result._p[] = this._p[] + rhs._p[]; >> return result; >> } >> ... >> } >> >> unittest{ >> auto a = Vector3([2.0, 2.0, 0.0]); >> auto b = Vector3([1.0, 2.0, 1.0]); >> Vector3[] c = [a]; >> Vector3[] d = [b]; >> Vector3 e = a + b; // works >> Vector3[] f; >> f[] = c[] + d[]; // Error: invalid array operation 'f[] = c[] + d[]' because Vector3 doesn't support necessary arithmetic operations >> } >> >> how can I get this to work? >> >> Thanks > > you need to define the slice operators. e.g. > > auto opSlice() // no parameters to get whole slice eg. a[] > // can also define with opSlice(size_t i, size_t j) > // for access like a[ i .. j] > { > return _p; > } whoops. it may be complaining about lack of opSliceAssign i.e. `f[] =` again define this with no parameters for the whole slice or two for a[i .. j] = also note that you need to give memory for this array assignment to go. eg. >> auto a = Vector3([2.0, 2.0, 0.0]); >> auto b = Vector3([1.0, 2.0, 1.0]); >> Vector3[] c = [a]; >> Vector3[] d = [b]; >> Vector3 e = a + b; // works >> Vector3[] f; >> f[] = c[] + d[]; will likely crash because `f` doesn't point to any allocated memory. initialising like Vector3[] f = [Vector3()]; Enhancement Request to tell you the names of the missing methods required filed at https://issues.dlang.org/show_bug.cgi?id=14772 |
July 06, 2015 Re: Array operations with array of structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Peter | On Monday, 6 July 2015 at 01:16:54 UTC, Peter wrote:
> Hi,
> I have a struct with arithmetic operations defined using opBinary but array operations with arrays of it don't work.
>
> struct Vector3 {
> public double[3] _p;
> ...
> Vector3 opBinary(string op)(in Vector3 rhs) const
> if (op == "+"){
> Vector3 result;
> result._p[] = this._p[] + rhs._p[];
> return result;
> }
> ...
> }
>
> unittest{
> auto a = Vector3([2.0, 2.0, 0.0]);
> auto b = Vector3([1.0, 2.0, 1.0]);
> Vector3[] c = [a];
> Vector3[] d = [b];
> Vector3 e = a + b; // works
> Vector3[] f;
> f[] = c[] + d[]; // Error: invalid array operation 'f[] = c[] + d[]' because Vector3 doesn't support necessary arithmetic operations
> }
>
> how can I get this to work?
>
> Thanks
Works for me with various versions of dmd on linux. What compiler are you using, what version of it, what operating system, etc?
|
July 06, 2015 Re: Array operations with array of structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nicholas Wilson | On Monday, 6 July 2015 at 03:02:59 UTC, Nicholas Wilson wrote: > On Monday, 6 July 2015 at 01:16:54 UTC, Peter wrote: [...] >> unittest{ >> auto a = Vector3([2.0, 2.0, 0.0]); >> auto b = Vector3([1.0, 2.0, 1.0]); >> Vector3[] c = [a]; >> Vector3[] d = [b]; >> Vector3 e = a + b; // works >> Vector3[] f; >> f[] = c[] + d[]; // Error: invalid array operation 'f[] = c[] + d[]' because Vector3 doesn't support necessary arithmetic operations >> } >> >> how can I get this to work? >> >> Thanks > > you need to define the slice operators. e.g. > > auto opSlice() // no parameters to get whole slice eg. a[] > // can also define with opSlice(size_t i, size_t j) > // for access like a[ i .. j] > { > return _p; > } `f`, `c`, and `d` are arrays though, not `Vector3`s. The code doesn't try to slice a Vector3. So as far as I can see, there's no point in adding opSlice to it. |
July 06, 2015 Re: Array operations with array of structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous | On Monday, 6 July 2015 at 10:29:35 UTC, anonymous wrote:
> Works for me with various versions of dmd on linux. What compiler are you using, what version of it, what operating system, etc?
dmd 2.066.1, windows 7 64bit
|
July 06, 2015 Re: Array operations with array of structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Peter | On Monday, 6 July 2015 at 12:15:22 UTC, Peter wrote:
> dmd 2.066.1, windows 7 64bit
Tested it on Windows 7, using dmd 2.066.1: works for me.
The exact code I tested (just commented those "..." out):
----
struct Vector3 {
public double[3] _p;
//...
Vector3 opBinary(string op)(in Vector3 rhs) const
if (op == "+"){
Vector3 result;
result._p[] = this._p[] + rhs._p[];
return result;
}
//...
}
unittest{
auto a = Vector3([2.0, 2.0, 0.0]);
auto b = Vector3([1.0, 2.0, 1.0]);
Vector3[] c = [a];
Vector3[] d = [b];
Vector3 e = a + b;
Vector3[] f;
f[] = c[] + d[];
}
----
And the command line: dmd -main -unittest test.d
|
July 07, 2015 Re: Array operations with array of structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous | On Monday, 6 July 2015 at 15:48:28 UTC, anonymous wrote: Ok, I disabled everything in the struct except what I posted and it ran. I then uncommented stuff to isolate the cause. I've added in the bits that cause the error below (plus some constructors just for reference). struct Vector3 { public double[3] _p; @nogc this(in double[] p) { switch ( p.length ) { case 0: _p[0] = _p[1] = _p[2] = 0.0; break; case 1: _p[0] = p[0]; _p[1] = _p[2] = 0.0; break; case 2: _p[0] = p[0]; _p[1] = p[1]; _p[2] = 0.0; break; default: _p[0] = p[0]; _p[1] = p[1]; _p[2] = p[2]; break; } } @nogc this(in double p0, in double p1=0.0, in double p2=0.0) { _p[0] = p0; _p[1] = p1; _p[2] = p2; } @nogc this(in Vector3 other) { _p[] = other._p[]; } //... Vector3 opBinary(string op)(in Vector3 rhs) const if (op == "+"){ Vector3 result; result._p[] = this._p[] + rhs._p[]; return result; } // The bits that cause the error: //... Enabling any one (or more) of the following causes the error this(this) { _p = _p.dup; } @nogc ref Vector3 opAssign(ref Vector3 rhs) { _p[] = rhs._p[]; return this; } @nogc ref Vector3 opAssign(Vector3 rhs) { _p[] = rhs._p[]; return this; } //... } Any ideas about what's happening? |
July 08, 2015 Re: Array operations with array of structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Peter | On Tue, 07 Jul 2015 11:09:52 +0000, Peter wrote: > Any ideas about what's happening? yes. there is code in "arrayop.c" that tells: // Built-in array ops should be @trusted, pure, nothrow and nogc StorageClass stc = STCtrusted | STCpure | STCnothrow | STCnogc; under the hoods compiler rewrites `f[] = c[]+d[];` to this: _arraySliceSliceAddSliceAssign_S3z007Vector3 extern (C) Vector3[] (Vector3[] p2, const Vector3[] p1, const Vector3[] p0) pure nothrow @nogc @trusted { foreach (p; 0u .. p2.length) { p2[p] = cast(Vector3)(p0[p] + p1[p]); } return p2; } _arraySliceSliceAddSliceAssign_S3z007Vector3(f, c, d); do you see the gotcha? if you uncomment postblit or assigns, this build function fails to compile, as that operations aren't "pure nothrow @nogc @trusted", and they will be used for either assign or postblitting. the same will happen if you add anything to your `opBinary` which make it unpure/@system (like `writeln`, for example). i.e. Vector3 opBinary(string op : "+") (in Vector3 rhs) const { import std.stdio; writeln("opBinary"); // (1) Vector3 result; result.vdata[] = this.vdata[] + rhs.vdata[]; return result; } BOOM! adding (1) is enough to get the same error. this is what is going on. i don't know why DMD insists on such restrictions for array operations, though. |
July 11, 2015 Re: Array operations with array of structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to ketmar | On Wednesday, 8 July 2015 at 06:05:54 UTC, ketmar wrote:
> do you see the gotcha? if you uncomment postblit or assigns, this build function fails to compile, as that operations aren't "pure nothrow @nogc @trusted", and they will be used for either assign or postblitting.
So after looking into it a little bit...
It looks like the opAssigns can take all the attributes without throwing errors so that's good.
The postblit can only not take @nogc due to the array duplication which is understandable.
I think the postblit might be redundant anyway since the struct is built on a static array so there is no possibility of two different Vect3s "pointing" to the same data.
Can someone confirm or does the postblit do anything else?
|
Copyright © 1999-2021 by the D Language Foundation