Решенный: Я выяснил очевидный способ, чтобы сделать это с 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()
.
Вы можете изучить 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 тройного оператора, вам не повезло.
зачем? C ++ - императивный язык. Выражения есть просто выражения. Используйте функциональные языки, если вы хотите делать все как выражения / функции.
У меня такое ощущение, что у вас просто есть функциональная спецификация (например, с точки зрения предварительных и последующих условий) того, как должен выполняться процесс перевода . Поскольку C ++ является не декларативным языком, а императивным, вы должны сами разработать процедурную реализацию этого процесса перевода , прежде чем начнете кодировать. И, как вы уже видели, это не так просто, как объединить все ваши исходные выражения с помощью запятых.
Вы пытаетесь заставить компилятор C ++ делать вашу работу за вас. Это не сработает, поскольку C ++ не является декларативным языком, и его компилятор не будет динамически пытаться интерпретировать то, что вы имели в виду из ваших спецификаций. И, если бы это могло сработать, C ++ должен был бы быть просто еще одним динамическим декларативным языком, и вы, вероятно, нацелились бы на другой статический язык.
Подсказка о том, что может работать: полностью проанализировать каждое исходное выражение (с его возможными побочными эффектами) и только потом выводить код. Если ваше выражение составное (в нем есть подвыражения), не выводите ничего, пока не проанализируете большее выражение.