【问题标题】:Elegant way for "if(T t = ...) { } else return t;"?“if(T t = ...) { } else return t;”的优雅方式?
【发布时间】:2015-10-28 06:12:18
【问题描述】:

这个“成语”有没有更好的办法?

if(State s = loadSomething()) { } else return s;

换句话说,我想做一些事情,它可能会返回错误(带有消息)或成功状态,如果有错误我想返回它。这可能会变得非常重复,所以我想缩短它。例如

if(State s = loadFoobar(&loadPointer, &results)) { } else return s;
if(State s = loadBaz(&loadPointer, &results)) { } else return s;
if(State s = loadBuz(&loadPointer, &results)) { } else return s;

这不能使用我喜欢的异常(不适合此构建)。我可以写一个小类BooleanNegator<State> 来存储值,并否定它的布尔评估。但我想避免做这种临时性的,而是更喜欢增强/标准解决方案。

【问题讨论】:

  • 我认为 State 有一个布尔运算符,对吧?
  • @Brahim 没错,没错
  • 并且您不想将s 的范围提升到if 块之外,对吗?
  • @CoryKramer 对。在成功的情况下,有一些信息,比如加载元素的加载地址和一些我并不总是需要的东西。
  • 如果你能做类似if(State s = loadSomething(), !s) 这样的事情,最好的解决方案可能是将其中一个“嘈杂”的解决方案包装在一个宏中

标签: c++ if-statement boolean conditional-statements


【解决方案1】:

你可以这样做:

for (State s = loadSomething(); !s; ) return s;

但我不确定它是否更优雅,而且它的可读性肯定更低......

【讨论】:

  • 啊,这绝对是创意!
  • 有趣! :) 但我想我不想在我维护的代码中看到它:P
【解决方案2】:

我假设上下文类似于

State SomeFunction()
{
     if(State s = loadSomething()) { } else return s;
     return do_something_else();
}

不抛出异常,do_something_else()SomeFunction() 相关并返回State。无论哪种方式,在函数内继续执行的结果都需要返回 State,因为从末尾掉下来会导致调用者表现出未定义的行为。

在这种情况下,我只需将函数重组为

State SomeFunction()
{
     if (State s = loadSomething())
        return do_something_else();
     else
        return s;
}

隐含的假设是State 有一些可以测试的运算符(例如operator bool()),复制State 是可能的(暗示存在返回一个的loadSomething())并且相对便宜,并且State 的两个实例可以同时存在。

【讨论】:

    【解决方案3】:

    除了一些巧妙/巧妙地使用不同的关键字来获得相同的行为,或者添加或多或少复杂的额外模板或宏来获得 unless() 关键字或以某种方式设法注入 ! 运算符,我' d 只做基本的事情。

    这是我(可能)注入额外“不必要”括号的地方之一:

    void someFunction()
    {
        // some other code
    
        { State s = loadSomething(); if(!s) return s; }
    
        // some other code
    }
    

    但是,在这种情况下,我会将其扩展为强调 return 关键字,当它被压缩为单行时很容易被忽略。所以,除非单行重复很多次,除非里面有一个return 很明显,否则我可能会写:

    void someFunction()
    {
        // some other code
    
        {
            State s = loadSomething();
            if(!s)
                return s;
        }
    
        // some other code
    }
    

    这看起来像是提升s 的范围,但实际上它相当于在if() 中声明State s。多亏了额外的括号,它们明确限制了本地 s 的可见性。

    然而,有些人只是“讨厌”看到{ .. } 没有与关键字/类/函数/等结合,甚至认为它不可读,因为“暗示 if/while/etc 关键字被意外删除” .

    添加重复示例后,我又想到了一个想法。您可以尝试从脚本语言中知道的技巧,其中 &&|| 可能返回非布尔值:

    State s = loadFoobar(&loadPointer, &results);
    s = s || loadBaz(&loadPointer, &results);
    s = s || loadBuz(&loadPointer, &results);
    if(!s) return s;
    

    但是有一个问题:与脚本语言相比,在 C++ 中 &&|| lose their short-circuit semantics 的重载使得这种尝试毫无意义。

    然而,正如 dyp 指出的显而易见的事情,一旦提升了s 范围,现在可以引入简单的if。可以通过额外的{} 再次限制其可见性:

    {
        State s;
        if(!(s = loadFoobar(&loadPointer, &results))) return s;
        if(!(s = loadBaz(&loadPointer, &results))) return s;
        if(!(s = loadBuz(&loadPointer, &results))) return s;
    }
    

    【讨论】:

    • s || (s = loadBaz(..)); 应该可以正常工作:在这种情况下不需要重载||,我们只需要从State 转换为bool(我们已经有了)。
    • @dyp:似乎我忽略了显而易见的事情!谢谢!我会把它编织到帖子中
    猜你喜欢
    • 2018-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 1970-01-01
    • 1970-01-01
    • 2015-12-13
    相关资源
    最近更新 更多