Re: opCast using in template struct
On 10/19/2012 06:38 AM, Oleg wrote: Problem solved partially. http://dpaste.dzfl.pl/e7871a01 in structs I use fix length arrays declarations, and alias its to structs, but not allowed casting to fix length arrays. I want check array length in compile time auto opBinary(string op,E)( E[DLen] b ) // fix length array E[DLen] is good above. You can also consider taking by 'const ref' if DLen is too large. Otherwise, being value-types, fixed-length arrays normally get copied to functions. if( ( op == + || op == - ) is( E : T ) ) { // without this checking in runtime //if( DLen != b.length ) // throw new Exception(bad length); Yes, that is not needed anymore because now it is known that b.length is always DLen. auto res = VecT(this); foreach( i, ref m; mixin( res. ~ DName ) ) mixin( m ~ op ~ = b[i]; ); return res; } if I write E[DLen] I have errors like this Error: template opop.vec!(xyz).vec.arrayMath!(data,3LU,double,vec!(xyz)).opAssign does not match any function template declaration Error: template opop.vec!(xyz).vec.arrayMath!(data,3LU,double,vec!(xyz)).opAssign(E) if (is(E : T)) cannot deduce template function from argument types !()(int[]) The problem is that array literals are slices, not fixed-length arrays. pragma(msg, typeof([1,2,3])); prints int[] but declaration like this allowed int[4] f = [1,2,3,4]; Because in that case the type of f is explicitly int[4]. The following would not be: auto f = [1,2,3]; The type of f is int[]. Of course it is possible to support both arrays and slices, and avoid the check by something like isStaticArray, but your callers will have to be aware of the fact that array literals are slices. Ali
Re: opCast using in template struct
On Thursday, 18 October 2012 at 23:51:44 UTC, Timon Gehr wrote: If the issue _is_ with the signature, then the compiler should tell you. That is the (secondary) job of the compiler. But not everything is parsed/compiled if it doesn't match the constraints, especially template functions. Sometimes I wish I had more information of what signatures it generated, what it compared against, and why each of them were disqualified; But that's regarding more complex stuff. That is a lot better, but what if the typo is within the first 3 characters? :o) If the beginning doesn't match 'op(Op)?[A-Z]', then you can't safely guess it was ever intended to override operators. If it has the keyword override then you know in a class it's polymorphic, however in a struct Hmmm... i don't know. Maybe a small suite list of tests that go through a few dozen templates and tells you what a struct qualifies for, like ranges, random access, forward/reverse, infinite. Etc. Might be more informational but if you expect you struct to do something and it doesn't qualify then you have a better idea at least of what is wrong.
Re: opCast using in template struct
Problem solved partially. http://dpaste.dzfl.pl/e7871a01 in structs I use fix length arrays declarations, and alias its to structs, but not allowed casting to fix length arrays. I want check array length in compile time auto opBinary(string op,E)( E[DLen] b ) // fix length array if( ( op == + || op == - ) is( E : T ) ) { // without this checking in runtime //if( DLen != b.length ) //throw new Exception(bad length); auto res = VecT(this); foreach( i, ref m; mixin( res. ~ DName ) ) mixin( m ~ op ~ = b[i]; ); return res; } if I write E[DLen] I have errors like this Error: template opop.vec!(xyz).vec.arrayMath!(data,3LU,double,vec!(xyz)).opAssign does not match any function template declaration Error: template opop.vec!(xyz).vec.arrayMath!(data,3LU,double,vec!(xyz)).opAssign(E) if (is(E : T)) cannot deduce template function from argument types !()(int[]) but declaration like this allowed int[4] f = [1,2,3,4]; also checked in compile time assigning like this int[4] f; int[5] g; g = f; // - Error: mismatched array lengths, 5 and 4 I think in my situation checking in compile time must be possibly, because all of template params known in compile time, but I unknown how to use it...
opCast using in template struct
Hello. How to cast template struct to itself? struct vec(string S,T=double) { T[S.length] data; auto opCast(string K,E)() if( S.length == K.length is( T : E ) ) { vec!(K,E) ret; foreach( i, ref m; ret.data ) m = data[i]; return ret; } } unittest { alias vec!xyz dvec3; alias vec!(rbg,float) fcol3; auto a = dvec3([1,2,3]); auto b = fcol3(); b = a; #1 assert( b.data == [1,2,3] ); } #1 Error: cannot implicitly convert expression (a) of type vec!(xyz) to vec!(rbg,float)
Re: opCast using in template struct
Sorry. My problem more complex and my simplification is not correct. I want use mixin for math operations. mixin template vectOp( string DataName, int DataLen, T, vecType ) { mixin( alias ~ DataName ~ this; ); auto opBinary(string op,E)( E[DataLen] b ) auto opBinary(string op,E)( E[] b ) auto opOpBinary(string op,E)( E[] b ) auto opOpBinary(string op,E)( E[DataLen] b ) } struct vec(string S,T=double) { T[S.length] data; mixin vectOp( data, S.length, T, vec!(S,T) ); } unittest{ vec!xyz a; vec!xyz b; a += b; } and it isn't work Error: 'a += b' is not a scalar, it is a vec!(xyz) Error: 'a._data' is not of arithmetic type, it is a double[3LU] Error: 'b._data' is not of arithmetic type, it is a double[3LU]
Re: opCast using in template struct
On 2012-10-18, 17:45, Oleg wrote: Sorry. My problem more complex and my simplification is not correct. I want use mixin for math operations. mixin template vectOp( string DataName, int DataLen, T, vecType ) { mixin( alias ~ DataName ~ this; ); auto opBinary(string op,E)( E[DataLen] b ) auto opBinary(string op,E)( E[] b ) auto opOpBinary(string op,E)( E[] b ) auto opOpBinary(string op,E)( E[DataLen] b ) } struct vec(string S,T=double) { T[S.length] data; mixin vectOp( data, S.length, T, vec!(S,T) ); } unittest{ vec!xyz a; vec!xyz b; a += b; } and it isn't work Error: 'a += b' is not a scalar, it is a vec!(xyz) Error: 'a._data' is not of arithmetic type, it is a double[3LU] Error: 'b._data' is not of arithmetic type, it is a double[3LU] I see you have opOpBinary there - should those be opOpAssign? -- Simen
Re: opCast using in template struct
On Thursday, 18 October 2012 at 18:12:49 UTC, Simen Kjaeraas wrote: I see you have opOpBinary there - should those be opOpAssign? Probably. It's an easy mistake to make. Maybe the compiler should issue a warning when opAssign attempts and fails and opOpBinary is defined.
Re: opCast using in template struct
Era Scarecrow: It's an easy mistake to make. Maybe the compiler should issue a warning when opAssign attempts and fails and opOpBinary is defined. If you have strong feelings about this, then add a Bugzilla entry. There are other cases. Generally the D compiler should add some warnings that help against operator overloading mistakes. Bye, bearophile
Re: opCast using in template struct
On 10/18/2012 11:45 PM, bearophile wrote: Era Scarecrow: It's an easy mistake to make. Maybe the compiler should issue a warning when opAssign attempts and fails and opOpBinary is defined. This would have to be implemented very carefully. There are enough hard to reproduce symbol resolution bugs already. It does not get better by introducing hidden and unnecessary lookups. If you have strong feelings about this, then add a Bugzilla entry. There are other cases. Generally the D compiler should add some warnings that help against operator overloading mistakes. Bye, bearophile I don't think that operator overloading gives rise to distinct mistakes. For example, better error messages that just specify the expected name, as in other cases of undefined identifiers, would already fix this.
Re: opCast using in template struct
On Thursday, 18 October 2012 at 22:07:55 UTC, Timon Gehr wrote: On 10/18/2012 11:45 PM, bearophile wrote: There are other cases. Generally the D compiler should add some warnings that help against operator overloading mistakes. I don't think that operator overloading gives rise to distinct mistakes. For example, better error messages that just specify the expected name, as in other cases of undefined identifiers, would already fix this. Inside a function a badly named identifier becomes obvious since it outright tells you. But with regards to opOpAssign and other operator overloading I see the error message and I see the call but I don't see why it fails. Then I'll try adjusting the signature on my function, not realizing it never sees it in the first place due to misspelling. Maybe.. A general warning when something starts with 'op(Op)?[A-Z]' but doesn't actually qualify as any of the override-able operators? That seems sensible...
Re: opCast using in template struct
Era Scarecrow: Maybe.. A general warning when something starts with 'op(Op)?[A-Z]' but doesn't actually qualify as any of the override-able operators? That seems sensible... Regarding operator overloading there are several situations worth warning the programmer of. The D compilers should be improved on this. Bye, bearophile
Re: opCast using in template struct
On 10/19/2012 01:05 AM, Era Scarecrow wrote: On Thursday, 18 October 2012 at 22:07:55 UTC, Timon Gehr wrote: On 10/18/2012 11:45 PM, bearophile wrote: There are other cases. Generally the D compiler should add some warnings that help against operator overloading mistakes. I don't think that operator overloading gives rise to distinct mistakes. For example, better error messages that just specify the expected name, as in other cases of undefined identifiers, would already fix this. Inside a function a badly named identifier becomes obvious since it outright tells you. But with regards to opOpAssign and other operator overloading I see the error message and I see the call but I don't see why it fails. My suggestion was something like: error: expression 'e' of type 'S' is not of arithmetic type and it does not define opOpAssign!+. The compiler should indicate exactly why it fails. If this is not enough, then the programmer certainly deserves the headache. Then I'll try adjusting the signature on my function, not realizing it never sees it in the first place due to misspelling. If the issue _is_ with the signature, then the compiler should tell you. That is the (secondary) job of the compiler. Maybe.. A general warning when something starts with 'op(Op)?[A-Z]' 'op[A-Z]' but doesn't actually qualify as any of the override-able operators? That seems sensible... That is a lot better, but what if the typo is within the first 3 characters? :o)
Re: opCast using in template struct
On 10/19/2012 01:23 AM, bearophile wrote: Era Scarecrow: Maybe.. A general warning when something starts with 'op(Op)?[A-Z]' but doesn't actually qualify as any of the override-able operators? That seems sensible... Regarding operator overloading there are several situations worth warning the programmer of. The D compilers should be improved on this. Bye, bearophile What situations?
Re: opCast using in template struct
Timon Gehr: What situations? This thread has already shown two possible cases worth discussing about. This report shows two more cases: http://d.puremagic.com/issues/show_bug.cgi?id=8844 Two more cases: Foo opBinary(string op=/\)(Foo f) {} Foo opBinary(string op)(Foo f) if (op == @) {} And several other situations. Bye, bearophile
Re: opCast using in template struct
On 10/19/2012 02:12 AM, bearophile wrote: Timon Gehr: What situations? This thread has already shown two possible cases worth discussing about. This report shows two more cases: http://d.puremagic.com/issues/show_bug.cgi?id=8844 How is that bug-prone? Are there keyboards where : and = are close? Two more cases: Foo opBinary(string op=/\)(Foo f) {} That is not even going to pass the lexing stage. Foo opBinary(string op)(Foo f) if (op == @) {} What is the issue? And several other situations. Bye, bearophile