Выход из середины выражения без использования исключений - PullRequest
1 голос
/ 21 апреля 2010

Решено: Я нашел чистый способ сделать это с setjmp() / longjmp(), требуя только минимальную оболочку, такую ​​как:

int jump(jmp_buf j, int i) { longjmp(j, i); return 0; }

Это позволяет jump()использоваться в условных выражениях.Итак, теперь код:

if (A == 0) return;
output << "Nonzero.\n";

правильно переведен на:

return
((A == 0) && jump(caller, 1)),
(output << "Nonzero.\n"),
0;

Где caller - это jmp_buf назад к точке вызова в вызывающей функции.Чистый, простой и эффективный до степени, которая намного меньше определяется реализацией, чем исключения.Спасибо за вашу помощь!


Есть ли способ эмулировать использование конструкций управления потоком в середине выражения?Возможно ли в выражении x, y, разделенном запятыми, для y вызвать return?

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

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

try {

    return
    x(),                        // x();
    (1 ? throw Return(0) : 0);  // return 0;

} catch (Return& ret) {

    return ref.value;

}

Оператор return всегда существует (в случае, если конструкция Return не достигнута), и поэтомуthrow должен быть заключен в ?:, чтобы компилятор отключился, чтобы его void результат использовался в выражении.

Я действительно хотел бы избежать использования исключений для управления потоком, если только вв этом случае может быть показано, что никаких особых накладных расходов не возникает;вызывает ли исключение сброс или что-нибудь здесь?Этот код должен работать с разумной эффективностью.Мне просто нужен функциональный эквивалент exit().

Ответы [ 3 ]

1 голос
/ 21 апреля 2010

Возможно, вы захотите исследовать cfront, программу конца 80-х - начала 90-х, которая переводила C ++ в C (тогда не было шаблонов или исключений), потому что было немного, если вообще было, нативных компиляторов C ++. 1002 *

То, как он обрабатывает встроенные функции, очень похоже на то, что вы пытаетесь сделать: множество триных (?:) операторов, запятых и скобок. Однако он не может преобразовать встроенную функцию с потоком управления более сложным, чем если / то, например, цикл for или while для выражения и должен был бы реализовать эту функцию как не встроенную.

Единственный способ «преждевременного выхода из выражения, разделенного запятыми», - это использование триничного оператора и скобок. Например:

(
    first thing,
    second thing,
    test expression?
    (
        next thing if successful,
        another thing,
        return value
    )
    :( // How often can you use an emoticon as an operator, anyway?
        something to do if unsuccessful,
        more cleanup,
        return value
    )
)

Если компилятор не закорачивает предложения then и else оператора trinary, вам не повезло.

1 голос
/ 21 апреля 2010

зачем? С ++ является обязательным языком. Выражения есть только выражения. Используйте функциональные языки, если вы хотите делать все как выражения / функции.

0 голосов
/ 21 апреля 2010

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

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

Подсказка о том, что может сработать: полностью проанализировать каждое исходное выражение (с его возможными побочными эффектами) и только затем выводить код. Если ваше выражение составное (оно содержит подвыражения), ничего не выводите, пока не проанализируете большее выражение.

...