优雅的方式为“if(T t = ...){} else返回t;”?

时间:2015-08-05 12:48:35

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

这个“成语”有更好的方法吗?

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>,并否定它的布尔值。但我想避免这样做,并且更喜欢增强/标准解决方案。

3 个答案:

答案 0 :(得分:10)

你可以这样做:

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

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

答案 1 :(得分:3)

我认为上下文类似于

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的两个实例可以同时存在。

答案 2 :(得分:3)

除了使用不同关键字的智能/ hacky来获得相同的行为,或者添加或多或少复杂的额外模板或宏来获取unless()关键字或以某种方式设法注入!操作员,我只坚持基本的事情。

这是我(可能)注入额外&#34;不必要&#34;的地方之一。括号:

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的范围,但实际上它相当于在State s中声明if()。所有这些都要归功于明确限制本地s的可见性的额外括号。

然而,有些人只是讨厌&#34;看到{ .. }没有与关键字/类/功能/等结合,或者甚至认为它是不可读的,因为&#34;提示if / while / etc关键字被意外删除&#34;。

在添加重复示例后,又有一个想法来找我。您可以尝试使用脚本语言中的一种技巧,其中&&||可能会返回非bool值:

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;
}