已解决:我想出了一个干净的方式来处理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
?
编辑:我正在编写一个编译器,而不是类似到函数式语言,目标语言是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()
的函数级别。
答案 0 :(得分:1)
为什么? C ++是命令式语言。表达式只是表达式。如果要将所有内容作为表达式/函数执行,请使用函数式语言。
答案 1 :(得分:1)
您可能想要研究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
)
)
如果编译器没有使trinary运算符的then和else子句短路,那你就不走运了。
答案 2 :(得分:0)
我觉得你只有一个功能规范(例如前后条件)必须如何执行翻译过程。由于C ++ 不是一种声明性语言,而是一种必需的语言,因此您必须在开始编码之前自己推导出该翻译过程的程序实现。而且,正如您已经看到的那样,它并不像使用逗号连接所有原始表达式那么简单。
您要做的是让C ++编译器为您完成工作。这不起作用,因为C ++不是声明性语言,并且它的编译器不会动态地尝试从您的规范解释你的意思。而且,如果这可行,C ++必须只是另一种动态声明语言,你可能会瞄准另一种静态语言。
提示可以的工作原理:完全分析每个原始表达式(带有可能的副作用),然后输出代码。如果你的表达式是复合的(它有子表达式),除非你分析了更大的表达式,否则不要输出任何东西。