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









"Paul Freund" <freund.paul lvl3.org> 