www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Some strange parameter deduction problems in opOpAssign and opBinary

reply "Ivan Agafonov" <armadil yandex.ru> writes:
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;
}
Sep 01 2012
next sibling parent "Ivan Agafonov" <armadil yandex.ru> writes:
Hmm, strange...
z.opOpAssign!"+"(z); works with both first and second versions
Sep 01 2012
prev sibling parent reply "Ivan Agafonov" <armadil yandex.ru> writes:
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.
Sep 01 2012
next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Sep 02 2012
prev sibling parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
 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.
Sep 02 2012
parent "Ivan Agafonov" <armadil yandex.ru> writes:
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)
Sep 02 2012