2

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.

Bauss
  • 2,767
  • 24
  • 28
  • The answers to http://stackoverflow.com/questions/28814898/mixins-names-parameterization-with-template-argument may be of interest. – rcorre Mar 06 '15 at 13:17
  • 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 Mar 06 '15 at 15:06
  • 1
    The second part of that answer, using aliases for give a nicer name, is I think the best you can do. – Adam D. Ruppe Mar 06 '15 at 16:05
  • 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 Mar 06 '15 at 16:10
  • 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 Mar 10 '15 at 23:13
  • That's what I thought! Anyways I just kept it as it is, thanks though. – Bauss Mar 11 '15 at 06:00

1 Answers1

0

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