2
votes

Is there a way to mixin function names (or for the matter any kind of member names) other than mixin strings?

I'm currently doing it like this:

mixin template PacketValue(T, string name, PacketMode mode, size_t offset) {
    import std.string : format;

    static if (mode == PacketMode.both || mode == PacketMode.write) {
        enum writePacketFormat = "void %s(T value) { write!T(value, offset); }";
        mixin(format(writePacketFormat, name));
    }

    static if (mode == PacketMode.both || mode == PacketMode.read) {
        enum readPacketFormat = "auto %s() { return read!T(offset); }";
        mixin(format(readPacketFormat, name));
    }
}

And it's used ex. like this:

class WritePacket : Packet!(PacketMode.write) {
    public:
        this(ushort size) {
            super(cast(ushort)1001, cast(ushort)(4 + size));
        }


    @property {
        mixin PacketValue!(uint, "value1", PacketMode.write, 4);
        mixin PacketValue!(uint, "value2", PacketMode.write, 8);
        mixin PacketValue!(ushort, "value3", PacketMode.write, 12);
    }
}

Where "value1", "value2" and "value3" will be the function names. In this case property functions.

I was just curious whether there's a better way to achieve this or not.

1
The answers to stackoverflow.com/questions/28814898/… may be of interest. - rcorre
No, already saw. They're relying on the same thing I am, using strings. Which is what I was asking if you could avoid. - Bauss
The second part of that answer, using aliases for give a nicer name, is I think the best you can do. - Adam D. Ruppe
Yeah, the input is still a string which was what I wanted to avoid, but yeah seems like there is no alternative! :) It'd be nice if you could mixin templates with an identifier or something. - Bauss
Either this identifier has already been declared somewhere in the code and you can use it directly, or you have to generate the code that declares it with a string mixin. - biozic

1 Answers

0
votes

An alternate approach would be opDispatch with a template condition for the name.

mixin template PacketValue(T, string name, PacketMode mode, size_t offset) {

static if (mode == PacketMode.both || mode == PacketMode.write)
{
    void opDispatch(string op,T)(T value) if (op == name)
    {
        write!T(value, offset);
    }
}

static if (mode == PacketMode.both || mode == PacketMode.read)
{
    auto opDispatch(string op)() if (op == name)
    {
        return read!T(offset);
    }
}

}

though you could probably streamline it into a single opDispatch