在编译时从现有列表构造列表

时间:2018-11-28 14:43:42

标签: d

我在程序模块中有一个全局项列表(每个项都有一些属性)。它是不可变的,并且在代码中静态定义,因此不必担心。

例如,假设我有蔬菜,它们只是一个别名,用name(字符串),code(ubyte)和price(ushort)将它们定义为一个不变的元组。

我希望能够通过namecode访问它们;所以我以为,因为蔬菜列表是在编译时就知道的,所以我可以构造对这些蔬菜的引用的关联数组(所以string => vegetable和ubyte => vegetable)

这是我想要实现的目标:

static struct instructions
{
    // list of Veggies

    immutable instr[] list = [
        Veggie("Potato" , 0xD0, 2),
        Veggie("Carrot" , 0xFE, 5),
    ];


    // genByCode and genByName being pure functions that get CTFE'd
    // and return the desired associative array

    immutable instr[ubyte]  byCode = genByCode(list);
    immutable instr[string] byName = genByName(list);


    // overloaded function returns the right Veggie

    instr get(string name) const
    { return byName[name]; }
    instr get(ubyte  code) const
    { return byCode[code]; }

}

具有以下形式的生成器功能(为清晰起见已被分隔)

pure instr[ubyte] genByCode(immutable Veggie[] list)
{
    instr[ubyte] res;
    foreach (i ; list)
        res[i.code] = i;
    return res;
}

我花了很多时间在弄乱,但我无法正常工作。当然,在运行时进行构造很简单,但是显然可以在编译时进行构造。

起初我以为这是一个可变性问题,所以我尝试将所有内容(蔬菜和蔬菜清单)都标记为不可变(无论如何都应该如此),但是后来我遇到了一些问题,我认为它们是不可变元组,并且感觉到太迷茫了,无法继续前进。

我可以从一个对这里起作用的机制有更清晰概述的人那里得到帮助吗?谢谢!

1 个答案:

答案 0 :(得分:0)

数据已经存在,无需构造编译时关联数组。

只需静态地对其进行迭代:

static auto get(int code)(){
    static foreach(veggie; list)
        static if(veggie.code == code)
            return veggie;
}

...

void main(){
    writeln(instructions.get!0xD0);
}

它可能比通过哈希映射表访问慢,但这就是CTFE的生命。

要确保它在编译时求值,可以使用以下代码:

template get(int code){
    static foreach(veggie; list)
        static if(veggie.code == code)
            alias get = veggie;
}