Thread overview
Strange Mixin issue
Mar 05, 2014
Frustrated
Mar 05, 2014
Ali Çehreli
Mar 05, 2014
Frustrated
Mar 05, 2014
Ali Çehreli
Mar 05, 2014
Ali Çehreli
Mar 05, 2014
Frustrated
Mar 05, 2014
Frustrated
Mar 05, 2014
Frustrated
Mar 05, 2014
Ali Çehreli
March 05, 2014
I am trying to remove the unnecessary passing of the type of class to a template but can't seem to get it to work:

see



The code is the

	
	mixin(AbstractToInterface!(WindowsGui, iButton, WindowsButton, iBorder, WindowsBorder));

which I want to not have to specify WindowsGui.

I've tried wrapping AbstractToInterface in a mixin template and use that and typeof(this) but then the mixin of the mixin does not get mixed in to the class

e.g.,

mixin template AbstractToInterface2(T...)
{
    mixin(AbstractToInterface!(typeof(this), T));
}

Then use mixin AbstractTointerface2!(iButton, WindowsButton, iBorder, WindowsBorder).

It's probably something stupid but I can't seem to get it to work(have a very similar case in some other code and it works fine... the only difference is I'm not using nested mixins.

March 05, 2014
On 03/05/2014 01:30 PM, Frustrated wrote:
> I am trying to remove the unnecessary passing of the type of class to a
> template but can't seem to get it to work:
>
> see
>
>
>
> The code is the
>
>
>      mixin(AbstractToInterface!(WindowsGui, iButton, WindowsButton,
> iBorder, WindowsBorder));
>
> which I want to not have to specify WindowsGui.
>
> I've tried wrapping AbstractToInterface in a mixin template and use that
> and typeof(this) but then the mixin of the mixin does not get mixed in
> to the class
>
> e.g.,
>
> mixin template AbstractToInterface2(T...)
> {
>      mixin(AbstractToInterface!(typeof(this), T));
> }
>
> Then use mixin AbstractTointerface2!(iButton, WindowsButton, iBorder,
> WindowsBorder).
>
> It's probably something stupid but I can't seem to get it to work(have a
> very similar case in some other code and it works fine... the only
> difference is I'm not using nested mixins.
>

The following works for me maybe because the templates are not mixin templates. What's a mixin template again?

import std.typetuple;

template fooImpl(This, T...)
{
    static assert(is (This == S));        // <-- IT WORKED!
    static assert(is (T == TypeTuple!(int, double)));
}

template foo(T...)
{
    alias foo = fooImpl!(typeof(this), T);
}

struct S
{
    mixin foo!(int, double);
}

void main()
{
    auto s = S();
}

Even better:

import std.typetuple;

template fooImpl(T...)
{
    static assert(is (T[0] == S));    // <-- COOL!
    static assert(is (T[1] == int));
    static assert(is (T[2] == double));
}

template foo(T...)
{
    alias foo = fooImpl!(TypeTuple!(typeof(this), T));
}

struct S
{
    mixin foo!(int, double);
}

void main()
{
    auto s = S();
}

Ali

March 05, 2014
On Wednesday, 5 March 2014 at 22:35:46 UTC, Ali Çehreli wrote:
> On 03/05/2014 01:30 PM, Frustrated wrote:
>> I am trying to remove the unnecessary passing of the type of class to a
>> template but can't seem to get it to work:
>>
>> see
>>
>>
>>
>> The code is the
>>
>>
>>     mixin(AbstractToInterface!(WindowsGui, iButton, WindowsButton,
>> iBorder, WindowsBorder));
>>
>> which I want to not have to specify WindowsGui.
>>
>> I've tried wrapping AbstractToInterface in a mixin template and use that
>> and typeof(this) but then the mixin of the mixin does not get mixed in
>> to the class
>>
>> e.g.,
>>
>> mixin template AbstractToInterface2(T...)
>> {
>>     mixin(AbstractToInterface!(typeof(this), T));
>> }
>>
>> Then use mixin AbstractTointerface2!(iButton, WindowsButton, iBorder,
>> WindowsBorder).
>>
>> It's probably something stupid but I can't seem to get it to work(have a
>> very similar case in some other code and it works fine... the only
>> difference is I'm not using nested mixins.
>>
>
> The following works for me maybe because the templates are not mixin templates. What's a mixin template again?
>
> import std.typetuple;
>
> template fooImpl(This, T...)
> {
>     static assert(is (This == S));        // <-- IT WORKED!
>     static assert(is (T == TypeTuple!(int, double)));
> }
>
> template foo(T...)
> {
>     alias foo = fooImpl!(typeof(this), T);
> }
>
> struct S
> {
>     mixin foo!(int, double);
> }
>
> void main()
> {
>     auto s = S();
> }
>
> Even better:
>
> import std.typetuple;
>
> template fooImpl(T...)
> {
>     static assert(is (T[0] == S));    // <-- COOL!
>     static assert(is (T[1] == int));
>     static assert(is (T[2] == double));
> }
>
> template foo(T...)
> {
>     alias foo = fooImpl!(TypeTuple!(typeof(this), T));
> }
>
> struct S
> {
>     mixin foo!(int, double);
> }
>
> void main()
> {
>     auto s = S();
> }
>
> Ali

this is not quite the same. You have static asserts. I'm trying to avoid mixing in ctfe code that might interfer with the class. (I have a temp function Do which if I mixin as a normal template will mixin Do into the class make Do a member of that class)

March 05, 2014
On 03/05/2014 02:37 PM, Frustrated wrote:

>> import std.typetuple;
>>
>> template fooImpl(T...)
>> {
>>     static assert(is (T[0] == S));    // <-- COOL!
>>     static assert(is (T[1] == int));
>>     static assert(is (T[2] == double));
>> }
>>
>> template foo(T...)
>> {
>>     alias foo = fooImpl!(TypeTuple!(typeof(this), T));
>> }
>>
>> struct S
>> {
>>     mixin foo!(int, double);
>> }
>>
>> void main()
>> {
>>     auto s = S();
>> }
>>
>> Ali
>
> this is not quite the same.

I think you tried to give a link in your original code but it is missing. Still, it is very difficult for me to follow code unless it is really simple. :)

> You have static asserts.

Just to prove that I've managed to inject typeof(this) as the first template parameter.

> I'm trying to avoid
> mixing in ctfe code that might interfer with the class. (I have a temp
> function Do which if I mixin as a normal template will mixin Do into the
> class make Do a member of that class)

The following is what I understand so far. :) The last line of main() proves that S gained a function Do() that takes (int, double) parameters.

import std.typetuple;

template DoImpl(T...)
{
    auto Do(T[1] p1, T[2] p2)
    {
        return p1 + p2;
    }
}

template Do(T...)
{
    mixin DoImpl!(TypeTuple!(typeof(this), T));
}

struct S
{
    mixin Do!(int, double);
}

void main()
{
    auto s = S();
    assert(s.Do(1, 2.5) == 3.5);
}

Ali

March 05, 2014
On 03/05/2014 03:04 PM, Ali Çehreli wrote:

> template Do(T...)
> {
>      mixin DoImpl!(TypeTuple!(typeof(this), T));

Actually, TypeTuple is not needed there:

    mixin DoImpl!(typeof(this), T);

Ali

March 05, 2014
On Wednesday, 5 March 2014 at 23:04:06 UTC, Ali Çehreli wrote:
> On 03/05/2014 02:37 PM, Frustrated wrote:
>
> >> import std.typetuple;
> >>
> >> template fooImpl(T...)
> >> {
> >>     static assert(is (T[0] == S));    // <-- COOL!
> >>     static assert(is (T[1] == int));
> >>     static assert(is (T[2] == double));
> >> }
> >>
> >> template foo(T...)
> >> {
> >>     alias foo = fooImpl!(TypeTuple!(typeof(this), T));
> >> }
> >>
> >> struct S
> >> {
> >>     mixin foo!(int, double);
> >> }
> >>
> >> void main()
> >> {
> >>     auto s = S();
> >> }
> >>
> >> Ali
> >
> > this is not quite the same.
>
> I think you tried to give a link in your original code but it is missing. Still, it is very difficult for me to follow code unless it is really simple. :)
>
> > You have static asserts.
>
> Just to prove that I've managed to inject typeof(this) as the first template parameter.
>
> > I'm trying to avoid
> > mixing in ctfe code that might interfer with the class. (I
> have a temp
> > function Do which if I mixin as a normal template will mixin
> Do into the
> > class make Do a member of that class)
>
> The following is what I understand so far. :) The last line of main() proves that S gained a function Do() that takes (int, double) parameters.
>
> import std.typetuple;
>
> template DoImpl(T...)
> {
>     auto Do(T[1] p1, T[2] p2)
>     {
>         return p1 + p2;
>     }
> }
>
> template Do(T...)
> {
>     mixin DoImpl!(TypeTuple!(typeof(this), T));
> }
>
> struct S
> {
>     mixin Do!(int, double);
> }
>
> void main()
> {
>     auto s = S();
>     assert(s.Do(1, 2.5) == 3.5);
> }
>
> Ali

And this is exactly what I don't what! Do, in my case, is a ctfe used only at compile time to make it easy to generate code. It's not needed at runtime and does not belong anywhere.
March 05, 2014
Maybe the problem isn't what I thought it was. I created a test case that works:

import std.stdio, std.cstream;

mixin template C()
{
	alias A = typeof(this);
	mixin(B!(A));
}

template B(T)
{
	pragma(msg, T);
	enum B() { return "string foo() { return `<"~T.stringof~">`; }"; }
}

class A
{
	//mixin(B!(A));
	mixin C;
}


void main()
{
	auto a = new A;
	writeln(a.foo());
	//a.B();
	din.getc();
}


Note the difference in calls. C is much easier because you don't have to pass the parent type. This is all I'm trying to achieve in the other code but when I do the functions(foo in this case) do not get mixed in.

March 05, 2014
On Wednesday, 5 March 2014 at 23:33:25 UTC, Frustrated wrote:
> Maybe the problem isn't what I thought it was. I created a test case that works:
>
> import std.stdio, std.cstream;
>
> mixin template C()
> {
> 	alias A = typeof(this);
> 	mixin(B!(A));
> }
>
> template B(T)
> {
> 	pragma(msg, T);
> 	enum B() { return "string foo() { return `<"~T.stringof~">`; }"; }
> }
>
> class A
> {
> 	//mixin(B!(A));
> 	mixin C;
> }
>
>
> void main()
> {
> 	auto a = new A;
> 	writeln(a.foo());
> 	//a.B();
> 	din.getc();
> }
>
>
> Note the difference in calls. C is much easier because you don't have to pass the parent type. This is all I'm trying to achieve in the other code but when I do the functions(foo in this case) do not get mixed in.


The actual error is quite strange in the other code:

When I simply wrap the code in an outside template I get the error(s)

Eror: gui.border is not an lvalue	

which is related to the line

auto ress = (gui.border = bb);

which works when I don't wrap the code. If I stick the output of the string mixin template directly into the class, it works fine. (so it has something to do wtih the template generation rather than what it generates)

e.g., this is what I did

template AbstractToInterface(B, T...)
{	
	enum AbstractToInterface() { .... }
}

to

mixin template AbstractToInterface(B, T...)
{
	mixin(AbstractToInterface2!(B, T));
}

template AbstractToInterface2(B, T...)
{	
	enum AbstractToInterface2() { .... }
}

and convert

mixin(AbstractToInterface!(WindowsGui, iButton, WindowsButton, iBorder, WindowsBorder));

to

mixin AbstractToInterface!(WindowsGui, iButton, WindowsButton, iBorder, WindowsBorder);


and I get the error down the road about

Eror: gui.border is not an lvalue

Which I guess is saying border does not have a setter, which is what AbstractToInterface is suppose to be creating and adding... again, it works when I copy the output of the template direct to the class.

I'm betting it's a bug unless I'm doing something real stupid.

March 05, 2014
On 03/05/2014 03:10 PM, Frustrated wrote:

>>     assert(s.Do(1, 2.5) == 3.5);

> And this is exactly what I don't what!

Sorry, I've completely misunderstood. :)

> Do, in my case, is a ctfe used
> only at compile time to make it easy to generate code. It's not needed
> at runtime and does not belong anywhere.

So, you want to mixin what D() generates. The following example mixes in a static member function and two variables to S:

// Makes a make() function that returns a T
string makeMakeFunc(T)()
{
    import std.string;

    return format("static %s make() { %s result; return result; }",
                  T.stringof, T.stringof);
}

unittest
{
    assert(makeMakeFunc!int() ==
           "static int make() { int result; return result; }",
           makeMakeFunc!int());
}

// Declares a make() function that returns T[0] and two variables of types
// T[1], T[2], etc.
string DoImpl(T...)()
{
    import std.conv;

    string result;
    size_t i = 0;

    foreach (Type; T[1 .. $]) {
        result ~= Type.stringof ~ " var" ~ i.to!string ~ ";\n";
        ++i;
    }

    result ~= makeMakeFunc!(T[0])();

    return result;
}

unittest
{
    assert(DoImpl!(int, double, long) ==
"double var0;
long var1;
static int make() { int result; return result; }");
}

// Declares a make() function that returns typeof(this) and two variables of
// types T[0], T[1], etc.
template Do(T...)
{
    mixin(DoImpl!(typeof(this), T)());
}

struct S
{
    mixin Do!(int, double);
}

void main()
{
    // S has a static member function that makes an S:
    auto s = S.make();
    static assert(is (typeof(s) == S));

    // S has gained two member variables:
    static assert(is (typeof(s.var0) == int));
    static assert(is (typeof(s.var1) == double));
}

Ali