Выход с середины выражения без Использования исключений

Решенный: Я выяснил очевидный способ, чтобы сделать это с 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 a jmp_buf назад на грани вызова в функции вызова. Чистый, простой, и эффективный в известной степени, который намного менее определяется реализацией, чем исключения.Спасибо за помощь!


Существует ли способ эмулировать использование конструкций управления потоком посреди выражения? Действительно ли это возможно в разграниченном запятой выражении x, y, для y вызвать a return?

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

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

try {

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

} catch (Return& ret) {

    return ref.value;

}

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

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

1
задан Jon Purdy 21 April 2010 в 14:28
поделиться

3 ответа

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

Способ обработки встроенных функций очень похож на то, что вы пытаетесь сделать: множество тройных (?: ) операторов, запятых и круглых скобок. Однако он не мог преобразовать встроенную функцию с более сложным потоком управления, чем if / then, например цикл 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 тройного оператора, вам не повезло.

1
ответ дан 3 September 2019 в 01:08
поделиться

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

1
ответ дан 3 September 2019 в 01:08
поделиться

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

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

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

0
ответ дан 3 September 2019 в 01:08
поделиться
Другие вопросы по тегам:

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