代码之家  ›  专栏  ›  技术社区  ›  Jon Purdy

从表达式中间退出而不使用异常

  •  1
  • Jon Purdy  · 技术社区  · 14 年前

    解决了的: 我想出了一个干净利落的办法 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++逗号。在语言中,流控制结构到目前为止没有出现任何问题;它只是 返回 . 我只需要一种方法来过早地退出逗号分隔的表达式,并且我不希望使用异常,除非有人能向我证明在这种情况下它们没有过多的开销。

    当然,问题是大多数流控制结构不是C++中的法律表达式。到目前为止,我找到的唯一解决方案是这样的:

    try {
    
        return
        x(),                        // x();
        (1 ? throw Return(0) : 0);  // return 0;
    
    } catch (Return& ret) {
    
        return ref.value;
    
    }
    

    这个 返回 语句始终存在(如果 Return 未达到构造),因此 throw 必须包在里面 ?: 让编译器闭嘴 void 表达式中使用的结果。

    我真的希望避免在流控制中使用异常,除非在这种情况下可以证明不会产生任何特定的开销;抛出异常是否会导致展开或这里的任何内容?此代码需要以合理的效率运行。我只需要一个等价于 exit() .

    3 回复  |  直到 14 年前
        1
  •  1
  •   Mike DeSimone    14 年前

    你可能想研究一下 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子句,你就走运了。

        2
  •  1
  •   Andrey    14 年前

    为何?C++是势在必行的语言。表达式只有表达式。如果您想以表达式/函数的形式执行所有操作,请使用函数语言。

        3
  •  0
  •   isekaijin    14 年前

    我觉得你只是对翻译过程的执行方式有了一个功能说明(比如说前后条件)。因为C++是 一种声明性语言,但又是一种命令性语言,您必须派生出该翻译过程的程序实现。 之前 你开始编码。而且,正如您已经看到的,它并不像使用逗号连接所有原始表达式那样简单。

    你要做的是让C++编译器为你做你的工作。这是行不通的,因为C++不是声明性语言,编译器不会动态地尝试。 解释你的意思 根据您的规格。而且,如果这是可行的,C++必须是另一种动态声明语言,而你可能会以另一种静态语言为目标。

    关于什么的提示 能够 工作:完全分析每个原始表达式(及其可能的副作用),然后输出代码。如果表达式是复合的(它有子表达式),在分析较大的表达式之前不要输出任何内容。