Solved: I figured out a clean way to do it with setjmp()
/longjmp()
, requiring only a minimal wrapper like:
int jump(jmp_buf j, int i) { longjmp(j, i); return 0; }
This allows jump()
to be used in conditional expressions. So now the code:
if (A == 0) return;
output << "Nonzero.\n";
Is correctly translated to:
return
((A == 0) && jump(caller, 1)),
(output << "Nonzero.\n"),
0;
Where caller
is a jmp_buf
back to the point of invocation in the calling function. Clean, simple, and efficient to a degree that is far less implementation-defined than exceptions. Thank you for your help!
Is there a way to emulate the use of flow-control constructs in the middle of an expression? Is it possible, in a comma-delimited expression x, y
, for y
to cause a return
?
Edit: I'm working on a compiler for something rather similar to a functional language, and the target language is C++. Everything is an expression in the source language, and the sanest, simplest translation to the destination language leaves as many things expressions as possible. Basically, semicolons in the target language become C++ commas. In-language flow-control constructs have presented no problems thus far; it's only return
. I just need a way to prematurely exit a comma-delimited expression, and I'd prefer not to use exceptions unless someone can show me that they don't have excessive overhead in this situation.
The problem of course is that most flow-control constructs are not legal expressions in C++. The only solution I've found so far is something like this:
try {
return
x(), // x();
(1 ? throw Return(0) : 0); // return 0;
} catch (Return& ret) {
return ref.value;
}
The return
statement is always there (in the event that a Return
construct is not reached), and as such the throw
has to be wrapped in ?:
to get the compiler to shut up about its void
result being used in an expression.
I would really like to avoid using exceptions for flow control, unless in this case it can be shown that no particular overhead is incurred; does throwing an exception cause unwinding or anything here? This code needs to run with reasonable efficiency. I just need a function-level equivalent of exit()
.