Thread overview
Enum template with mixin, need 'this'
Dec 24, 2014
Meta
Dec 24, 2014
ketmar
Dec 24, 2014
Meta
Dec 24, 2014
ketmar
Dec 24, 2014
Meta
Dec 24, 2014
Meta
December 24, 2014
The code I currently have is as follows:

import std.stdio;
import std.traits;
import std.typecons;

struct EmbeddedTest
{
    int bits;
}

struct Test
{
    //Other stuff
	
    EmbeddedTest embeddedTest;

    enum isSet(alias bit) = `cast(bool)(embeddedTest.bits & `
                                ~ bit.stringof ~ `)`;

    @property setBits()
    {
        enum Bits = EnumMembers!Bit;
        Nullable!(Bit, Bit.max)[Bits.length] ret;
        foreach (i, bit; Bits)
        {
            if (mixin(isSet!bit))
            {
                ret[i] = bit;
            }
        }
		
		return ret;
    }
}

enum Bit
{
    bit1 = 0x0001,
    bit2 = 0x0002,
    bit3 = 0x0004,
    bit4 = 0x0008,
}
									
void main()
{
	Test t;
	t.embeddedTest.bits = 0x1;
	foreach (bit; t.setBits)
	{
		if (!bit.isNull)
		{
			writeln(bit);
		}
	}
}

My problem is that I would like to not have to mixin the result of Test.isSet at each usage site, but I also want to avoid making it a function if possible. I tried to move the mixin into isSet like this:


    enum isSet(alias bit) = mixin(`cast(bool)(embeddedTest.bits & `
                                ~ bit.stringof ~ `)`);

This would now break isSet for usage outside of the struct Test. However, I don't see why it wouldn't work inside of Test, since the mixin expands, for example, to:

    cast(bool)(embeddedTest.bits & bit1)

So `if (isSet!bit1)` becomes `if (cast(bool)(embeddedTest.bits & bit1)`. That doesn't work, however. I get an error message saying "need 'this' for 'bits' of type 'int'". Is there a way to make this work, or am I stuck with the uglier mixin at the usage site?
December 24, 2014
On Wed, 24 Dec 2014 17:05:45 +0000
Meta via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote:

> So `if (isSet!bit1)` becomes `if (cast(bool)(embeddedTest.bits & bit1)`. That doesn't work, however. I get an error message saying "need 'this' for 'bits' of type 'int'". Is there a way to make this work, or am I stuck with the uglier mixin at the usage site?

i don't think that you can cheat like this. ;-)

templates aren't macros, and `mixin` inside the template works immediately. i.e. it's trying to *execute* the mixined code in compile time. so your template with `mixin` in it tries to check `embedded.bits` in *compile* time, and then complains about missing 'this', as it should.

i don't think that you can do c-like macros in D.


December 24, 2014
On Wednesday, 24 December 2014 at 17:41:09 UTC, ketmar via Digitalmars-d-learn wrote:
> On Wed, 24 Dec 2014 17:05:45 +0000
> Meta via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote:
>
>> So `if (isSet!bit1)` becomes `if (cast(bool)(embeddedTest.bits & bit1)`. That doesn't work, however. I get an error message saying "need 'this' for 'bits' of type 'int'". Is there a way to make this work, or am I stuck with the uglier mixin at the usage site?
>
> i don't think that you can cheat like this. ;-)
>
> templates aren't macros, and `mixin` inside the template works
> immediately. i.e. it's trying to *execute* the mixined code in
> compile time. so your template with `mixin` in it tries to check
> `embedded.bits` in *compile* time, and then complains about missing
> 'this', as it should.
>
> i don't think that you can do c-like macros in D.

Hmm, I confused myself over when the expression is interpreted. I got it into my head that the template expansion would somehow delay interpretation of the expression so it could be picked up at runtime, but of course `enum` forces it to be CTFE'd.
December 24, 2014
On Wed, 24 Dec 2014 19:52:31 +0000
Meta via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote:

> Hmm, I confused myself over when the expression is interpreted. I got it into my head that the template expansion would somehow delay interpretation of the expression so it could be picked up at runtime, but of course `enum` forces it to be CTFE'd.

sometimes i want to have some kind of C-like macros in D too, which just inserts the generated string in the place of instantiation with implicit `mixin`. maybe someone will write a DIP/ER for this...


December 24, 2014
I am curious, however, why changing `enum` to `auto` (or bool) doesn't work. You said that the mixin tries to interpret the expression `cast(bool)(embeddedTest.bits & <enumName>)` at compile time, but I don't understand why that would be so when the storage is auto and not enum. I guess mixin doesn't work quite like I thought it did; it's not quite the equivalent of pasting the mixed-in code.
December 24, 2014
On Wednesday, 24 December 2014 at 20:08:07 UTC, Meta wrote:
> I am curious, however, why changing `enum` to `auto` (or bool) doesn't work. You said that the mixin tries to interpret the expression `cast(bool)(embeddedTest.bits & <enumName>)` at compile time, but I don't understand why that would be so when the storage is auto and not enum. I guess mixin doesn't work quite like I thought it did; it's not quite the equivalent of pasting the mixed-in code.

Ok, I understand now. I missed the fact that even when it's an auto or a bool variable, it is CTFE-initialized because it's outside the constructor. I'm so close, yet so far from making this work.