gcc 流量控制、优化

d7v8vwbk  于 2023-10-19  发布在  其他
关注(0)|答案(2)|浏览(154)

我在gcc中滥用异常作为流控制,有没有办法让它发出一些优化的代码?

shiny f(legacy const &l)
try
{
    auto convert_i = [](int i) -> int
    {
        switch(i)
        {
            case 1:    return 5;
            case 2:    return 9;
            default:   throw 0;
        }
    };

    return shiny
    {
        .i = convert_i(l.i)
    };
}
catch(int)
{
    return shiny { .invalid = true };
}

所以我有很多异常,这些都是在填充一个结构体时使用的,几乎所有这些都可能失败,所以写这些没有异常的代码将是一个冗长的混乱。同时,异常永远不会离开当前函数,编译器生成异常处理代码的唯一原因就是给予调试器干预的机会。
这个项目使用gcc作为编译器,并且不太可能改变。生成的代码使用大量的空间来构造,抛出,捕获和忽略异常对象,这可以避免吗?

iq3niunx

iq3niunx1#

将您的代码更改为使用std::optional将能够完全删除异常路径。有几种方法可以做到这一点,但是代码的一个相当直接的翻译可能看起来像这样:

shiny f(legacy const &l)
{
    auto convert_i = [](int i) -> std::optional<int>
    {
        switch (i)
        {
        case 1:
            return 5;
        case 2:
            return 9;
        default:
            return {};
        }
    };

    auto c = convert_i(l.i);
    if (c)
        return shiny{.i = c.value()};
    else
        return shiny{.invalid = true};
}
vxqlmq5t

vxqlmq5t2#

我想对你问题的前提提出质疑。你说 “所以写这段没有异常的代码将是一个冗长的混乱”.但这是真的吗那么,以下几点呢?
除此之外:我大胆猜测,所有这些本地的数据也会导致大量的开销。为什么不把它们变成带输出参数bool &conversion_failed的静态函数呢?不需要捕获局部变量和生成临时函数指针(除非它们被gcc优化掉)。

shiny f(legacy const &l)
{
    bool conversion_failed = false;

    auto convert_i = [&conversion_failed](int i) -> int
    {
        // Feel free to omit this line if you can accept that all conversions are run even after any one failed.
        if (conversion_failed) return 0; // or any nonsense value
        switch(i)
        {
            case 1:    return 5;
            case 2:    return 9;
            default:   conversion_failed = true;
                       return 0; // or any nonsense value
        }
    }

    shiny result {
        .i = convert_i(l.i),
        // etc...
    };
    result.invalid = conversion_failed;

    return result;
}

相关问题