Вопрос

Я использую урожай во многих моих программах Python, и это В самом деле Очищает код во многих случаях. я Об этом И это один из популярных страниц моего сайта.

C # также предлагает урожайность - это реализуется с помощью состояния в стороне абоненты, выполненная через автоматически сгенерированный класс, который сохраняет состояние, локальные переменные функции и т. Д.

Я в настоящее время читаю о C ++ 0x и его дополнениях; И во время чтения о внедрении лямбдаса в C ++ 0x я ухожу, что это было сделано через автоматически сгенерированные классы, оснащенные оператором () хранения лямбда-кода. Естественный вопрос, сформированный в моей голове: они сделали это для лямбдаса, почему они не считают его для поддержки «доходности» тоже?

Конечно, они могут видеть ценность ко-процессов ... поэтому я могу только догадаться, что они думают, что реализации на основе макросов (например, Саймон Тафтам) как адекватный заменитель. Однако они не являются, однако по многим причинам: Callee-хранит государство, нерентарный, на основе макроса (в одиночку это причина) и т. Д.

Редактировать: yield не зависит от сбора мусора, нитей или волокна. Вы можете прочитать статью Саймона, чтобы увидеть, что я говорю о компиляторе, выполняя простое преобразование, например:

int fibonacci() {
    int a = 0, b = 1;
    while (true) {
        yield a;
        int c = a + b;
        a = b;
        b = c;
    }
}

В:

struct GeneratedFibonacci {
    int state;
    int a, b;

    GeneratedFibonacci() : state (0), a (0), b (1) {}

    int operator()() {
        switch (state) {
        case 0:
            state = 1;
            while (true) {
                return a;

        case 1:
                int c = a + b;
                a = b;
                b = c;
            }
        }
    }
}

Вывоз мусора? Нет. Темы? Нет. Волокна? Нет. Простое преобразование? Возможно, да.

Это было полезно?

Решение

Они сделали это для лямбдаса, почему они не считали его для поддержки доходности тоже?

Проверить документы. Отказ Кто-нибудь предложил это?

... Я могу только догадаться, что они считают реализации на основе макроса, чтобы быть адекватной заместителем.

Не обязательно. Я уверен, что они знают, что такие макросные решения существуют, но замена их недостаточно мотивации, самостоятельно, чтобы получить новые функции.


Несмотря на то, что вокруг нового ключевого слова существуют различные проблемы, те могут быть преодолены с новым синтаксисом, например, было сделано для лямбдаса и использования AUTO в качестве типа возврата функции.

Радикально новые функции нуждаются в сильных водителях (т.е. людей), чтобы полностью проанализировать и подтолкнуть функции через Комитет, поскольку у них всегда будет много людей скептически относиться к радикальному изменению. Так что даже отсутствует то, что вы бы посмотрели как сильную техническую причину против конструкции доходности, возможно, не было достаточно поддержки.

Но принципиально стандартная библиотека C ++ приняла другую концепцию итераторов, чем у вас увидимся. Сравните итераторы Python, которые требуют только двух операций:

  1. an_iter.next () возвращает следующий элемент или повышает запечатление (следующий () встроенный в комплектую 2,6 вместо использования метода)
  2. ITER (AN_ITER) возвращает AN_ITR (так что вы можете лечить Iterables и итераторы идентично в функциях)

Итераторы C ++ используются в парах (которые должны быть одинаковыми типами), разделены на категории, это было бы семантическим сдвигом для перехода в нечто более отдаленное к конструкции доходности, и этот сдвиг не будет хорошо подходить с концепциями (что имеет С тех пор было снижено, но это пришло относительно поздно). Например, см. обоснование Для (оправданно, если он узошь), отвергая мой комментарий к изменению диапазона для петлей к форме, которая сделает написание этой другой формы итератора намного проще.

Для конкретно уточнить, что я имею в виду о различных формах итератора: ваш пример пример кода еще один Тип, чтобы стать тиратором типа плюс связанный механизм для получения и поддержания этих итераторов. Не то чтобы он не мог быть обработан, но это не так просто, как вы можете сначала представить. Настоящая сложность - это «простое преобразование», уважающие исключения для «локальных» переменных (в том числе во время строительства), контролируя срок службы «локальных» переменных в местных областях в пределах генератора (большинство понадобится сохранено по всему вызовам) и так далее.

Другие советы

Я не могу сказать, почему они не добавили что-то вроде этого, но в случае лямбда, они не были только что добавлен на язык тоже.

Они начали жизнь в качестве библиотечной реализации в Boost, что доказало, что

  • лямбдас широко полезно: многие люди будут использовать их, когда они доступны, и что
  • Реализация библиотеки в C ++ 03 страдает рядом недостатков.

Исходя из этого, Комитет решил принять какой-то лямбдаса в C ++ 0x, и я считаю, что они изначально экспериментировали с добавлением более общих языковых функций, чтобы позволить лучше Библиотечная реализация, чем Boost имеет.

И в конце концов, они сделали его функцией ядра языка, потому что у них не было другого выбора: потому что не удалось сделать достаточно хорошо Реализация библиотеки.

Новые функции основных языков не просто добавляются на язык, потому что они кажутся хорошей идеей. Комитет очень неохотно добавлять их, и рассматриваемая функция В самом деле нужно доказать себя. Должно быть показано, что функция:

  • можно реализовать в компиляторе,
  • собираюсь решить реальную потребность и
  • что реализация библиотеки не будет достаточно хорошей.

В случае, если yield Ключевое слово, мы знаем, что первая точка может быть решена. Как вы показали, это довольно простое преобразование, которое можно сделать механически.

Второй момент сложно. Сколько из нужно Ибо это там? Насколько широко используются реализации библиотеки, которые существуют? Сколько людей попросили об этом или представлены предложения для этого?

Последний пункт, кажется, тоже проходит. По крайней мере, в C ++ 03, реализация библиотеки страдает некоторыми недостатками, как вы указали, какие мог оправдать реализацию языка основных языков. Может ли лучшую реализацию библиотеки быть сделано в C ++ 0x, хотя?

Поэтому я подозреваю, что главная проблема - это действительно отсутствие интереса. C ++ уже огромный язык, и никто не хочет, чтобы он был больше, если не добавляются функции В самом деле стоило того. Я подозреваю, что это просто не полезно.

Добавление ключевого слова всегда сложно, потому что он недействителен ранее действительным кодом. Вы пытаетесь избежать этого на языке с кодовой базой, сколько C ++.

Эволюция C ++ является общедоступным процессом. Если ты чувствуешь yield Должно быть там, сформулировать подходящий запрос к стандартным комитету C ++.

Вы получите свой ответ, напрямую от людей, которые приняли решение.

Таким образом, похоже, что это не сделало его на C ++ 11 или C ++ 14, но может быть на пути к C ++ 17. Взглянуть на лекцию C ++ Coroutines, отрицательная надземная абстракция от CPPCON2015 и бумаги здесь.

Подводя итоги, они работают над расширением функций C ++, чтобы иметь доходность и ждать функций функций. Похоже, у них есть первоначальная реализация в Visual Studio 2015, не уверена, что у Clang есть реализация еще. Также кажется, что их могут быть некоторые проблемы с использованием доходности и ждут как ключевые слова.

Представление интересна, потому что он говорит о том, насколько он упрощенный сетевой код, где вы ждете данных, чтобы продолжить последовательность обработки. Удивительно, что он выглядит как используя эти новые CONOUTINES, приводит к более быстрому / меньше, чем то, что нужно было бы сегодня. Это отличная презентация.

Предложение о возобновляемых функциях для C ++ можно найти здесь.

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

Одно можно помнить о комитете C ++, заключается в том, что это добровольческий комитет, и не может достичь всего, что он хочет. Например, в исходном стандарте не было карты типа HASH, потому что им не удалось сделать это вовремя. Может быть, что в комитете никого не было достаточно осторожно yield И что это делает, чтобы убедиться, что работа сделана.

Лучший способ узнать было бы спросить участника активного комитета.

Ну, для такого тривиального примера, как то, единственная проблема, которую я вижу, это то, что std::type_info::hash_code() не указан constexpr. Отказ Я считаю, что соответствующая реализация все еще может сделать это и поддерживать это. Во всяком случае, реальная проблема является получение уникальных идентификаторов, поэтому может быть другой раствор. (Очевидно, я позаимствовал ваш «главный коммутатор», спасибо.)

#define YIELD(X) do { \
    constexpr size_t local_state = typeid([](){}).hash_code(); \
    return (X); state = local_state; case local_state: ; } \
while (0)

Применение:

struct GeneratedFibonacci {
    size_t state;
    int a, b;

    GeneratedFibonacci() : state (0), a (0), b (1) {}

    int operator()() {
        switch (state) {
        case 0:
            while (true) {
                YIELD( a );
                int c = a + b;
                a = b;
                b = c;
            }
        }
    }
}

Хм, им также потребуется гарантировать, что хеш тоже нет 0. Большая бига. И а DONE Макрос легко реализовать.


Настоящая проблема - это то, что происходит, когда вы вернетесь с объема с местными объектами. Нет надежды на сохранение кадра стека в языке на основе C. Решением является использование реального COROUTINE, а C ++ 0x делает непосредственно обращаться с тем, что с потоками и фьючерсами.

Рассмотрим этот генератор / COROUTINE:

void ReadWords() {
    ifstream f( "input.txt" );

    while ( f ) {
        string s;
        f >> s;
        yield s;
    }
}

Если аналогичный трюк используется для yield, f уничтожен в первом yield, и незаконно продолжать петлю после него, потому что вы не можете goto или switch последнее определение объекта без стручки.

Было несколько реализации COROOTINES в качестве библиотек по пользовательским пространствам. Однако, и вот сделка, эти реализации полагаются на нестандартные детали. Например, нигде на стандарте C ++ указан, как хранятся кадры стека. Большинство реализаций просто копируют стек, потому что это как большинство реализаций C ++ работают

Что касается стандартов, C ++ может помочь поддержке Coroutine, улучшая спецификацию кадров стека.

На самом деле «добавляя» это на язык, не звучит мне хорошая идея для меня, потому что это будет придерживаться вас «достаточно хорошей» реализацией для большинства случаев, которые полностью зависят от компилятора. Для случаев, когда используя вопросы COROUTINE, это в любом случае недопустимо

Согласен с @Potatoswatter первым.

Для поддержки COROUTINE не то же самое, что поддержка лямбдаса, а не то, что Простое преобразование Как играл с устройством Даффа.

Тебе нужно Полноасимметричные CITONINES. (штабел) работать как генераторы в Python. Реализация Саймон Тафтам а также Крис' оба стекляны во время Boost.Coroutine. это стек, хотя это тяжело.

К сожалению, C ++ 11 до сих пор не имеет yield Для Coroutines пока, возможно, C ++ 1y;)

PS: если вам действительно нравятся генераторы в стиле Python, посмотрите на это.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top