Jump to page: 1 2
Thread overview
opCast using in template struct
Oct 18, 2012
Oleg
Oct 18, 2012
Simen Kjaeraas
Oct 18, 2012
Oleg
Oct 18, 2012
Simen Kjaeraas
Oct 18, 2012
Era Scarecrow
Oct 18, 2012
bearophile
Oct 18, 2012
Timon Gehr
Oct 18, 2012
Era Scarecrow
Oct 18, 2012
bearophile
Oct 18, 2012
Timon Gehr
Oct 19, 2012
bearophile
Oct 19, 2012
Timon Gehr
Oct 18, 2012
Timon Gehr
Oct 19, 2012
Era Scarecrow
Oct 19, 2012
Oleg
Dec 08, 2012
Ali Çehreli
October 18, 2012
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)
October 18, 2012
On 2012-10-18, 16:54, Oleg wrote:

> 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)

I don't see a cast there. Do you?

What you want is to overload the assignment operator, opAssign:

struct vec(string S,T=double)
{
    T[S.length] data;
    void opAssign(string K,E)(vec!(K,E) value)
        if( S.length == K.length &&
             is( E : T ) )
    {
        foreach( i, ref m; value.data )
            data[i] = m;
    }
}

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] );
}

-- 
Simen
October 18, 2012
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]
October 18, 2012
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
October 18, 2012
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.
October 18, 2012
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
October 18, 2012
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.
October 18, 2012
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...
October 18, 2012
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
October 18, 2012
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)
« First   ‹ Prev
1 2