digitalmars.D - Bug in mixins?
- Frustrated (31/31) Mar 06 2014 I have a mixin template that I use to make programming to
- Frustrated (43/43) Mar 06 2014 Can someone check this out? The best I can acertain is that the
- Paul Freund (4/48) Mar 07 2014 I admit I didn't read the entire description but maybe it is
- John Colvin (5/49) Mar 07 2014 functions introduced through mixin templates do not take part in
- Frustrated (7/75) Mar 07 2014 This seems to be the problem. The mixin thinks they are the same
- Artur Skawina (22/28) Mar 26 2014 You can explicitly add the function(s) to the overload set, ie
- Frustrated (13/52) Mar 28 2014 This is not really any better than just using a string mixin
I have a mixin template that I use to make programming to interfaces easier. The problem is when I try to wrap the template to reduce dependence on the container class(using typeof(this)) I get an error as the string mixin is not working. The code can be seen here http://dpaste.dzfl.pl/6c90ca418996 The lines are 77-81 and 162-163 that are the problems. AbstractToInterface(a mixin template) simply wraps AbstractToInterface2(a string mixin) (I haven't removed the container class dependency since it doesn't change anything yet but that is the goal) I have a simplified test case that does work(and does remove the extra parameter but, again, that isn't where the problem is). http://dpaste.dzfl.pl/dd8d1888da44 B is a string mixin template that depends on the container class(parameter T). I do not want to have to duplicate that argument though since it is not necessary. Hence where the mixin template C comes into play. It is able to get the container class type and pass it to B. There is no real difference between the two yet the first gives strange errors(I get different errors about assignment(lines 200 and 212) but dpaste gives more direct results(the properties to handle the general case are simply not mixed in). There should be no difference between the two code examples. They both essentially do the same thing(wrap a string mixin). Why one works and the other doesn't is beyond me.... seems like a bug unless I'm doing something really stupid. Any ideas? P.S. The specific error I get is "Error: gui.border is not an lvalue" which suggests that the setter properties are not being inserted.
Mar 06 2014
Can someone check this out? The best I can acertain is that the mixin template isn't adding the generated functions because it thinks they are already in the class. i.e., the code generates the following methods property iButton button(iButton b) property iBorder border(iBorder b) and the class contains the methods property WindowsButton button() property WindowsButton button(WindowsButton b) and the template mixin simply doesn't add the generic methods. (simply because mixing the string mixin directly works, wrapping it in a mixin template does not) Using that I created a MWE: http://dpaste.dzfl.pl/6f64e49aba95 import std.stdio, std.cstream; // mixin template used to wrap the string mixin mixin template C() { mixin(B); } // eponymously named template used as a string mixin to generate the function template B() { string B() { return "void foo(iA a) { writeln(`Generic`); }"; } } interface iA { void foo(iA a); } class A : iA { void foo(A a) { writeln("Specific"); } //mixin(B); mixin C; // doesn't work, use line above, does not insert generic foo } void main() { iA a = new A; a.foo(a); (cast(A)a).foo(cast(A)a); (cast(A)a).foo(a); // line doesn't work when using mixin template because the generic foo does not exist } This seems like a bug to me but maybe that's how mixin templates work? If so is there any way to make them insert the code regardless if it thinks they are the same? (they are not in this case and I need to use them to reduce redundancy)
Mar 06 2014
On Friday, 7 March 2014 at 06:23:58 UTC, Frustrated wrote:Can someone check this out? The best I can acertain is that the mixin template isn't adding the generated functions because it thinks they are already in the class. i.e., the code generates the following methods property iButton button(iButton b) property iBorder border(iBorder b) and the class contains the methods property WindowsButton button() property WindowsButton button(WindowsButton b) and the template mixin simply doesn't add the generic methods. (simply because mixing the string mixin directly works, wrapping it in a mixin template does not) Using that I created a MWE: http://dpaste.dzfl.pl/6f64e49aba95 import std.stdio, std.cstream; // mixin template used to wrap the string mixin mixin template C() { mixin(B); } // eponymously named template used as a string mixin to generate the function template B() { string B() { return "void foo(iA a) { writeln(`Generic`); }"; } } interface iA { void foo(iA a); } class A : iA { void foo(A a) { writeln("Specific"); } //mixin(B); mixin C; // doesn't work, use line above, does not insert generic foo } void main() { iA a = new A; a.foo(a); (cast(A)a).foo(cast(A)a); (cast(A)a).foo(a); // line doesn't work when using mixin template because the generic foo does not exist } This seems like a bug to me but maybe that's how mixin templates work? If so is there any way to make them insert the code regardless if it thinks they are the same? (they are not in this case and I need to use them to reduce redundancy)I admit I didn't read the entire description but maybe it is related to this https://d.puremagic.com/issues/show_bug.cgi?id=11954
Mar 07 2014
On Friday, 7 March 2014 at 06:23:58 UTC, Frustrated wrote:Can someone check this out? The best I can acertain is that the mixin template isn't adding the generated functions because it thinks they are already in the class. i.e., the code generates the following methods property iButton button(iButton b) property iBorder border(iBorder b) and the class contains the methods property WindowsButton button() property WindowsButton button(WindowsButton b) and the template mixin simply doesn't add the generic methods. (simply because mixing the string mixin directly works, wrapping it in a mixin template does not) Using that I created a MWE: http://dpaste.dzfl.pl/6f64e49aba95 import std.stdio, std.cstream; // mixin template used to wrap the string mixin mixin template C() { mixin(B); } // eponymously named template used as a string mixin to generate the function template B() { string B() { return "void foo(iA a) { writeln(`Generic`); }"; } } interface iA { void foo(iA a); } class A : iA { void foo(A a) { writeln("Specific"); } //mixin(B); mixin C; // doesn't work, use line above, does not insert generic foo } void main() { iA a = new A; a.foo(a); (cast(A)a).foo(cast(A)a); (cast(A)a).foo(a); // line doesn't work when using mixin template because the generic foo does not exist } This seems like a bug to me but maybe that's how mixin templates work? If so is there any way to make them insert the code regardless if it thinks they are the same? (they are not in this case and I need to use them to reduce redundancy)functions introduced through mixin templates do not take part in overload resolution when an overload exists outside the mixin. It's a common annoyance, I can't remember if there's a good reason for it.
Mar 07 2014
On Friday, 7 March 2014 at 09:10:45 UTC, John Colvin wrote:On Friday, 7 March 2014 at 06:23:58 UTC, Frustrated wrote:This seems to be the problem. The mixin thinks they are the same function so it doesn't insert it. I guess it just looks at the name rather than the complete signature. Would be real nice if that wasn't the case or if one could chose the behavior. I can see in some cases it being nice to have the current behavior but not all(specifically talking about overloads).Can someone check this out? The best I can acertain is that the mixin template isn't adding the generated functions because it thinks they are already in the class. i.e., the code generates the following methods property iButton button(iButton b) property iBorder border(iBorder b) and the class contains the methods property WindowsButton button() property WindowsButton button(WindowsButton b) and the template mixin simply doesn't add the generic methods. (simply because mixing the string mixin directly works, wrapping it in a mixin template does not) Using that I created a MWE: http://dpaste.dzfl.pl/6f64e49aba95 import std.stdio, std.cstream; // mixin template used to wrap the string mixin mixin template C() { mixin(B); } // eponymously named template used as a string mixin to generate the function template B() { string B() { return "void foo(iA a) { writeln(`Generic`); }"; } } interface iA { void foo(iA a); } class A : iA { void foo(A a) { writeln("Specific"); } //mixin(B); mixin C; // doesn't work, use line above, does not insert generic foo } void main() { iA a = new A; a.foo(a); (cast(A)a).foo(cast(A)a); (cast(A)a).foo(a); // line doesn't work when using mixin template because the generic foo does not exist } This seems like a bug to me but maybe that's how mixin templates work? If so is there any way to make them insert the code regardless if it thinks they are the same? (they are not in this case and I need to use them to reduce redundancy)functions introduced through mixin templates do not take part in overload resolution when an overload exists outside the mixin. It's a common annoyance, I can't remember if there's a good reason for it.
Mar 07 2014
On 03/07/14 20:22, Frustrated wrote:On Friday, 7 March 2014 at 09:10:45 UTC, John Colvin wrote:You can explicitly add the function(s) to the overload set, ie mixin template some_mixin_templ() { void f() {} } struct S { mixin some_mixin_templ blah; void f(int) {} alias f = blah.f; // add the one(s) from the mixin template } or use a string mixin (which is less problematic inside a /mixin/ template): mixin template some_mixin_templ(string CODE="") { void f() {} mixin (CODE); } struct S { mixin some_mixin_templ!q{ void f(int) {} }; } arturfunctions introduced through mixin templates do not take part in overload resolution when an overload exists outside the mixin. It's a common annoyance, I can't remember if there's a good reason for it.This seems to be the problem. The mixin thinks they are the same function so it doesn't insert it. I guess it just looks at the name rather than the complete signature. Would be real nice if that wasn't the case or if one could chose the behavior. I can see in some cases it being nice to have the current behavior but not all(specifically talking about overloads).
Mar 26 2014
On Wednesday, 26 March 2014 at 19:29:49 UTC, Artur Skawina wrote:On 03/07/14 20:22, Frustrated wrote:This is not really any better than just using a string mixin directly. You have to create a named mixin then create the aliases. In your example, you know the function being mixed in so it is easy. In my case, the function name was generated by a string mixin. So I'd basically have to have to mixins, one to generate the function itself and the other to generate the aliases, then I've have to call them both in the struct. Much worse than just passing the typeof(this) to the string mixin. The only way it could work is if I could use the alias inside the template mixin and it all work out. In any case, it's a very convoluted way to achieve what I want(which is simply not having to pass typeof(this) to the string mixin).On Friday, 7 March 2014 at 09:10:45 UTC, John Colvin wrote:You can explicitly add the function(s) to the overload set, ie mixin template some_mixin_templ() { void f() {} } struct S { mixin some_mixin_templ blah; void f(int) {} alias f = blah.f; // add the one(s) from the mixin template } or use a string mixin (which is less problematic inside a /mixin/ template): mixin template some_mixin_templ(string CODE="") { void f() {} mixin (CODE); } struct S { mixin some_mixin_templ!q{ void f(int) {} }; } arturfunctions introduced through mixin templates do not take part in overload resolution when an overload exists outside the mixin. It's a common annoyance, I can't remember if there's a good reason for it.This seems to be the problem. The mixin thinks they are the same function so it doesn't insert it. I guess it just looks at the name rather than the complete signature. Would be real nice if that wasn't the case or if one could chose the behavior. I can see in some cases it being nice to have the current behavior but not all(specifically talking about overloads).
Mar 28 2014