Thread overview
Some strange parameter deduction problems in opOpAssign and opBinary
Sep 02, 2012
Ivan Agafonov
Sep 02, 2012
Ivan Agafonov
Sep 02, 2012
Ivan Agafonov
Sep 02, 2012
Ali Çehreli
Sep 02, 2012
Philippe Sigaud
Sep 02, 2012
Ivan Agafonov
September 02, 2012
There are 3 separated versions of opOpAssign
first version must be the same as the second for Vec!(sometype, 4)
why it doesn't work?

Simplified code:

struct Vec(T, uint size)
{
	this(T rhs) { array[] = rhs; }
	
	// It doesn't work but compiles
	ref Vec!(T, size) opOpAssign(string op) (Vec!(T, size) rhs)
	{
		mixin("array[] "~op~"= rhs.array[];");
		return this;
	}
	
	// but it work's
	ref Vec!(T, 4) opOpAssign(string op) (Vec!(T, 4) rhs)
	{
		mixin("array[] "~op~"= rhs.array[];");
		return this;
	}
	
	// and this work;s
	ref Vec!(T, size) opAddAssign(Vec!(T, size) rhs)
	{
		array[] += rhs.array[];
		return this;
	}
	
	T[size] array = 0;
}

int main()
{
	auto z = Vec!(float, 4)(5.0f);
	z += z;
	writeln(z);
	return 0;
}
September 02, 2012
Hmm, strange...
z.opOpAssign!"+"(z); works with both first and second versions
September 02, 2012
On Sunday, 2 September 2012 at 04:10:39 UTC, Ivan Agafonov wrote:
> There are 3 separated versions of opOpAssign
> first version must be the same as the second for Vec!(sometype, 4)
> why it doesn't work?
>
> Simplified code:
>
> struct Vec(T, uint size)
> {
> 	this(T rhs) { array[] = rhs; }
> 	
> 	// It doesn't work but compiles
> 	ref Vec!(T, size) opOpAssign(string op) (Vec!(T, size) rhs)
> 	{
> 		mixin("array[] "~op~"= rhs.array[];");
> 		return this;
> 	}
> 	
> 	// but it work's
> 	ref Vec!(T, 4) opOpAssign(string op) (Vec!(T, 4) rhs)
> 	{
> 		mixin("array[] "~op~"= rhs.array[];");
> 		return this;
> 	}
> 	
> 	// and this work;s
> 	ref Vec!(T, size) opAddAssign(Vec!(T, size) rhs)
> 	{
> 		array[] += rhs.array[];
> 		return this;
> 	}
> 	
> 	T[size] array = 0;
> }
>
> int main()
> {
> 	auto z = Vec!(float, 4)(5.0f);
> 	z += z;
> 	writeln(z);
> 	return 0;
> }

Problem solved:

alias Vec!(T, size) V;

// This works fine
ref V opOpAssign(string op)(V rhs)
{
	mixin("array[] "~op~"= rhs.array[];");
		return this;
}

But I think this is a bug.
September 02, 2012
On 09/01/2012 10:08 PM, Ivan Agafonov wrote:
> On Sunday, 2 September 2012 at 04:10:39 UTC, Ivan Agafonov wrote:
>> There are 3 separated versions of opOpAssign
>> first version must be the same as the second for Vec!(sometype, 4)
>> why it doesn't work?
>>
>> Simplified code:
>>
>> struct Vec(T, uint size)
>> {
>> this(T rhs) { array[] = rhs; }
>>
>> // It doesn't work but compiles
>> ref Vec!(T, size) opOpAssign(string op) (Vec!(T, size) rhs)
>> {
>> mixin("array[] "~op~"= rhs.array[];");
>> return this;
>> }
>>
>> // but it work's
>> ref Vec!(T, 4) opOpAssign(string op) (Vec!(T, 4) rhs)
>> {
>> mixin("array[] "~op~"= rhs.array[];");
>> return this;
>> }
>>
>> // and this work;s
>> ref Vec!(T, size) opAddAssign(Vec!(T, size) rhs)
>> {
>> array[] += rhs.array[];
>> return this;
>> }
>>
>> T[size] array = 0;
>> }
>>
>> int main()
>> {
>> auto z = Vec!(float, 4)(5.0f);
>> z += z;
>> writeln(z);
>> return 0;
>> }
>
> Problem solved:
>
> alias Vec!(T, size) V;

You don't need the alias.

> // This works fine
> ref V opOpAssign(string op)(V rhs)
> {
> mixin("array[] "~op~"= rhs.array[];");
> return this;
> }

The name of the template alone becomes the actual instantiation of that template. This should work:

    ref Vec opOpAssign(string op) (Vec rhs)
    {
        mixin("array[] "~op~"= rhs.array[];");
        return this;
    }

> But I think this is a bug.

Which compiler? All three versions of your original code compiles and produces the same result with dmd 2.060 under 64-bit Linux.

Ali

September 02, 2012
> Problem solved:
>
> alias Vec!(T, size) V;
>
> // This works fine
> ref V opOpAssign(string op)(V rhs)
>
> {
>         mixin("array[] "~op~"= rhs.array[];");
>                 return this;
> }

Inside a template, you can refer to the current (local) instantiation by its name only. Try using 'Vec' instead of V. Does this work?

If you want to force the use of another instantiation, I personally put a dot ('.') before the template: this is the 'global scope' operator and the compiler will 'step out' of the current template.


September 02, 2012
On Sunday, 2 September 2012 at 07:44:12 UTC, Philippe Sigaud wrote:
>> Problem solved:
>>
>> alias Vec!(T, size) V;
>>
>> // This works fine
>> ref V opOpAssign(string op)(V rhs)
>>
>> {
>>         mixin("array[] "~op~"= rhs.array[];");
>>                 return this;
>> }
>
> Inside a template, you can refer to the current (local) instantiation by
> its name only. Try using 'Vec' instead of V. Does this work?
>
> If you want to force the use of another instantiation, I personally put a
> dot ('.') before the template: this is the 'global scope' operator and the
> compiler will 'step out' of the current template.

Yeah! Thanks. No need to alias. Needed simple Vec instead of Vec!(T, size)