View mode: basic / threaded / horizontal-split · Log in · Help
October 18, 2012
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)
October 18, 2012
Re: opCast using in template struct
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
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]
October 18, 2012
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
October 18, 2012
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.
October 18, 2012
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
October 18, 2012
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.
October 18, 2012
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...
October 18, 2012
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
October 18, 2012
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)
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home