www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - mixin not overloading other mixins, Bug or feature?

reply Travis Boucher <boucher.travis gmail.com> writes:
float func1(float[2] v) { return v[0]; }
float func1(float[3] v) { return v[0]; }

template Test (size_t S) {
	float func2(float[S] v) { return v[0]; }
}

mixin Test!(2);
mixin Test!(3);

void main() {
	float[2] a2;

	func1(a2);
	func2(a2);
}


Here the call to func1 is fine, but the call to func2 results in a conflict.

Test!(2).func2 conflicts with unit.Test!(3).func2

This was tested with ldc (dmd 1.051).

Is this a bug or a "feature"?
Dec 21 2009
parent reply BCS <none anon.com> writes:
Hello Travis,

 float func1(float[2] v) { return v[0]; }
 float func1(float[3] v) { return v[0]; }
 template Test (size_t S) {
 float func2(float[S] v) { return v[0]; }
 }
 mixin Test!(2);
 mixin Test!(3);
 void main() {
 float[2] a2;
 func1(a2);
 func2(a2);
 }
 Here the call to func1 is fine, but the call to func2 results in a
 conflict.
 
 Test!(2).func2 conflicts with unit.Test!(3).func2
 
 This was tested with ldc (dmd 1.051).
 
 Is this a bug or a "feature"?
 

IIRC it's a fature. I forget where, but I recall reading that they don't overload.
Dec 22 2009
parent reply Travis Boucher <boucher.travis gmail.com> writes:
BCS wrote:
 Hello Travis,
 
 float func1(float[2] v) { return v[0]; }
 float func1(float[3] v) { return v[0]; }
 template Test (size_t S) {
 float func2(float[S] v) { return v[0]; }
 }
 mixin Test!(2);
 mixin Test!(3);
 void main() {
 float[2] a2;
 func1(a2);
 func2(a2);
 }
 Here the call to func1 is fine, but the call to func2 results in a
 conflict.

 Test!(2).func2 conflicts with unit.Test!(3).func2

 This was tested with ldc (dmd 1.051).

 Is this a bug or a "feature"?

IIRC it's a fature. I forget where, but I recall reading that they don't overload.

I know they don't, I am just wondering why. Is it a side effect/oversight of the implementation (misfeature), something that is suppose to work (bug) or is there a concrete reason why (feature).
Dec 22 2009
parent reply BCS <none anon.com> writes:
Hello Travis,

 BCS wrote:
 
 Hello Travis,

 Is this a bug or a "feature"?
 

don't overload.

effect/oversight of the implementation (misfeature), something that is suppose to work (bug) or is there a concrete reason why (feature).

By don't overload, I'm taking about "defined to not overload". That removes "bug" leaving "misfeature", and "feature". I think the rational is that allowing them to overload makes the order of expansion hard to impossible to work out. For example: template Bar(T) { const bool v = true; } template Foo(T) { static if(Bar!(T).v) template Bar(U : T) { const bool v = false; } else template Bar(U : T) { const bool v = true; } } mixin Foo!(int); static assert(Bar!(char)); // works static assert(Bar!(int)); // what about this? By making mixins not overload, many (if not all) such cases become illegal.
Dec 22 2009
parent reply Travis Boucher <boucher.travis gmail.com> writes:
BCS wrote:
 By don't overload, I'm taking about "defined to not overload".
 
 That removes "bug" leaving "misfeature", and "feature".
 
 I think the rational is that allowing them to overload makes the order 
 of expansion hard to impossible to work out.
 For example:
 
 template Bar(T) { const bool v = true; }
 template Foo(T)
 {
   static if(Bar!(T).v)
       template Bar(U : T) { const bool v = false; }
   else
       template Bar(U : T) { const bool v = true; }
 }
 
 mixin Foo!(int);
 
 static assert(Bar!(char)); // works
 static assert(Bar!(int));  // what about this?
 
 By making mixins not overload, many (if not all) such cases become illegal.
 
 

I'm not fully sure this applies to my issue, maybe it is because I am not fully sure how templates are implemented (in my mind, I think something similar to macro expansion). My issue is with function overloads. 2 functions, same name, different parameters. Right now my only solution is hacky string mixins. It seems to me that 2 templates should be able to mix into the same struct, overloading the same functions, if: 1. They don't contain the same parameters with eachother. If they do, then conflict. 2. They don't contain the same parameters of the struct they are mixing into. If they do, then use the one in the struct (like it works now).
Dec 22 2009
parent BCS <none anon.com> writes:
Hello Travis,

 BCS wrote:
 
 By don't overload, I'm taking about "defined to not overload".
 
 That removes "bug" leaving "misfeature", and "feature".
 
 I think the rational is that allowing them to overload makes the
 order
 of expansion hard to impossible to work out.
 For example:
 template Bar(T) { const bool v = true; }
 template Foo(T)
 {
 static if(Bar!(T).v)
 template Bar(U : T) { const bool v = false; }
 else
 template Bar(U : T) { const bool v = true; }
 }
 mixin Foo!(int);
 
 static assert(Bar!(char)); // works
 static assert(Bar!(int));  // what about this?
 By making mixins not overload, many (if not all) such cases become
 illegal.
 

not fully sure how templates are implemented (in my mind, I think something similar to macro expansion).

Using CTFE, the above can be recast using functions. Or if you want to get tricky you can play games with different return types and generate the same kind of paradoxical results.
 
 My issue is with function overloads.  2 functions, same name,
 different parameters.  Right now my only solution is hacky string
 mixins.
 
 It seems to me that 2 templates should be able to mix into the same
 struct, overloading the same functions, if:
 
 1. They don't contain the same parameters with eachother.  If they do,
 then conflict.
 
 2. They don't contain the same parameters of the struct they are
 mixing into.  If they do, then use the one in the struct (like it
 works now).
 

That might work if you add "3. They have no effect on any overloading choices that were needed (directly or indirectly) to instance the template." But that might not be a reasonably computable criteria. And if it is reasonable, you can bet your socks it will be bug bait.
Dec 23 2009