Как сделать объект (класс) foreachable в D?

как я могу сделать класс применимым в foreach операторе?

Класс содержит ассоциативный массив (например, строка [строка]). Так foreach использование оператора этот массив как источник.

Таким образом, это - то, что я хочу:

auto obj = new Obj();
foreach (key, value; obj)
{
    ...
}

Я должен реализовать интерфейс что-то как этот?

Править:

Решение:

public int opApply(int delegate(ref string, ref Type) dg)
{
    int result = 0;

    foreach (ref key, ref value; data)
    {
        result = dg(key, value);
        if (result != 0)
        {
            break;
        }
    }

    return result;
}

То же сделано для общедоступного интервала opApply (международный делегат (касательно Типа) dg).

7
задан VDVLeon 15 June 2010 в 16:13
поделиться

2 ответа

D1 :

class Foo
{
    uint array[2];

    int opApply(int delegate(ref uint) dg)
    {
        int result = 0;

        for (int i = 0; i < array.length; i++)
        {
            result = dg(array[i]);
            if (result)
                break;
        }
        return result;
    }
}

D2 :

Итерация по объектам структур и классов может выполняться с диапазонами, что означает, что должен быть определен [набор] свойств:

4
ответ дан 7 December 2019 в 07:40
поделиться

Решение, опубликованное ОП, является правильным решением, но в D2 есть другое решение с другим набором компромиссов. Итерацию в D можно разделить на внутреннюю итерацию, которая обрабатывается opApply, и внешнюю итерацию, которая обрабатывается диапазонами.

Внутренняя итерация дает итерируемому объекту контроль над стеком вызовов. Это позволяет, например, использовать рекурсию для итерируемого объекта, не поддерживая явный стек, но делает невозможным итерацию нескольких структур в lockstep. Внешняя итерация делает обратное.

Внешняя итерация осуществляется с помощью диапазонов. Диапазон - это любой класс или структура, определяющая три метода: front() дает доступ к первому элементу в диапазоне, popFront() продвигает диапазон и empty() возвращает true, если диапазон пуст. Если диапазон бесконечен, empty может быть объявлена как константа вместо функции-члена. Таким образом, вызывающая сторона получает контроль над стеком вызовов, что является компромиссом, который может быть хорошим или плохим в зависимости от ситуации.

Вот пример использования диапазонов для итерации:

/**This struct lazily produces all Fibonacci numbers.*/
struct Fibonacci {
    ulong num1 = 0;
    ulong num2 = 1;

    ulong front() {
        return num1 + num2;
    }

    void popFront() {
        auto newNum2 = num1 + num2;
        num1 = num2;
        num2 = newNum2;
    }

    // A range of Fibonacci numbers is infinite.
    enum bool empty = false; 
}
3
ответ дан 7 December 2019 в 07:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: