D traits - Список интегральных членов данных

Я пытаюсь использовать следующий код, чтобы получить список интегральных членов данных из класса:

import std.stdio;
import std.traits;

class D
{
    static string[] integralMembers = getIntegralMembers();

    static string[] getIntegralMembers()
    {
        auto allMembers = __traits(allMembers, D);

        string[] tmp = new string[allMembers.length];
        int ct = 0;

        for(int i = 0; i != allMembers.length; ++i) {
            bool isInteg = __traits(isIntegral, __traits(getMember, D, allMembers[i]));
            if(isInteg) {
                tmp[ct++] = allMembers[i];
            }
        }

        string[] ret = new string[ct];

        for(int i = 0; i != ct; ++i) {
            ret[i] = tmp[i];
        }

        return ret;
    }

    int a;
    this() { }
    ~this() { }
}

void main()
{
    auto integralMembers = D.integralMembers;

    foreach(mem; integralMembers)
    {
        writeln(mem);
    }
}

Но компиляция завершается с этими ошибками:

main.d(17): Error: variable i cannot be read at compile time
main.d(17): Error: expression expected as second argument of __traits getMember
main.d(19): Error: variable i cannot be read at compile time
main.d(7):        called from here: getIntegralMembers()

Как мне сделать этот код скомпилированным?

1 ответ

Решение

Несмотря на то, что функция будет выполняться только во время компиляции в этой программе, она все равно должна быть скомпилирована как функция, которая может выполняться во время выполнения.

  1. Вы должны объявить allMembers как явная константа:

    enum allMembers = __traits(allMembers, D);
    

    allMembers это кортеж Если вы используете auto, он будет сохранен как кортеж строк в "стеке", став значением времени выполнения, таким образом недоступным для оценки времени компиляции для __traits,

  2. Вам нужно использовать foreach вместо for, foreach особенность над кортежем заключается в том, что он будет разворачиваться статически, поэтому индекс (и значение) будут доступны для __traits,

Фиксированная программа:

import std.stdio;
import std.traits;

class D
{
    static string[] integralMembers = getIntegralMembers();

    static string[] getIntegralMembers()
    {
        enum allMembers = __traits(allMembers, D);

        string[] tmp = new string[allMembers.length];
        int ct = 0;

        foreach(i, member; allMembers) {
            bool isInteg = __traits(isIntegral, __traits(getMember, D, member));
            if(isInteg) {
                tmp[ct++] = allMembers[i];
            }
        }

        string[] ret = new string[ct];

        for(int i = 0; i != ct; ++i) {
            ret[i] = tmp[i];
        }

        return ret;
    }

    int a;
    this() { }
    ~this() { }
}

void main()
{
    auto integralMembers = D.integralMembers;

    foreach(mem; integralMembers)
    {
        writeln(mem);
    }
}
Другие вопросы по тегам