Построить списки из существующих списков во время компиляции - PullRequest
0 голосов
/ 28 ноября 2018

У меня есть глобальный список элементов (каждый с несколькими свойствами) в модуле моей программы.Он неизменен и статически определен в коде, так что не беспокойтесь.

Например, скажем, у меня есть овощи, которые являются просто псевдонимом, определяющим их как неизменный кортеж с name (строка), code(ubyte) и price (ushort).

Я хотел бы получить доступ к ним либо по name, либо по code;так что я подумал, так как список овощей известен во время компиляции, я мог бы, вероятно, построить ассоциативные массивы со ссылками на эти овощи (так что string => vegetable and 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 голосов
/ 01 декабря 2018

Данные уже есть, не нужно создавать ассоциативный массив во время компиляции.

Просто переберите его статически:

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;
}
...