d中的x宏

原创
2022/08/21 16:52
阅读数 20

原文
C中的X宏非常适合从表格数据生成编译时代码.尤其是对微控制器上的引脚分配及其各自的功能,我还没有看到其他语言提供如此简洁,易于维护的方式来交互和表示数据.

挑战不大:

//你示例
enum Color { red, blue, green }
static immutable colorStrings = [EnumMembers!Color].map!text.array;
static foreach(color;EnumMembers!Color){ ... }

//维基1

auto value1=1,value2=2,value3=3;
alias vars=AliasSeq!(value1,value2,value3);
void printVariables(){
    static foreach(alias var;vars){
        writeln(__traits(identifier, var), " = ", var);
    }
}

维基2:

enum id1=1, id2=2, id3=3;

static immutable varList = [
    tuple("id1", "name1"),
    tuple("id2", "name2"),
    tuple("id3", "name3"),
];

static foreach(id, name; varList.map!(x=>x)){ // yuck
    mixin(`int `~name~`;`);
}

mixin(`enum MyIdListType{`~varList.map!(x=>x[1]~"="~x[0]).join(",")~`}`);

不允许透明添加新列,但我想我们需要实际元组模式匹配(或通过索引).

D颜色示例:

import std.traits, std.meta;

enum Color { red, blue, green }

enum getName(alias sym) = __traits(identifier, sym);
string[] colorStrings = [staticMap!(getName, EnumMembers!Color)];

unittest
{
    assert(colorStrings[Color.red] == "red");
    assert(colorStrings[Color.blue] == "blue");
    assert(colorStrings[Color.green] == "green");
}

由于可访问D中强大的编译时反射,可让枚举成为"真相源",并生成数组.
好的,但是如果想为与枚举成员串表示不同的名称怎么办?简单:

import std.traits, std.meta;

struct name { string str; }

enum Color
{
    @name("red") Cred,
    @name("blue") Cblue,
    @name("green") Cgreen
}

enum getName(alias sym) = getUDAs!(sym, name)[0].str;
string[] colorStrings = [staticMap!(getName, EnumMembers!Color)];

unittest
{
    assert(colorStrings[Color.Cred] == "red");
    assert(colorStrings[Color.Cblue] == "blue");
    assert(colorStrings[Color.Cgreen] == "green");
}

在C中,每个附加数据"列"都表示为X宏的附加参数.由于D的UDA允许附加任意数据到包括枚举成员符号,可转换这些附加参数为枚举成员的属性,并再次按真相源使用枚举.
反射的美妙在代码仍然是代码且像自动补全都正常工作.

本文同步分享在 博客“fqbqrr”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部