优雅的"if(T t = ...) { } else return t;"方式?
Elegant way for "if(T t = ...) { } else return t;"?
是否有更好的方法来实现这个"习语"?
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>
来存储这个值,并对它的布尔值求反。但是我希望避免这样做,而更喜欢一个增强/标准解决方案。
你可以这样做:
for (State s = loadSomething(); !s; ) return s;
但是我不确定它是否更优雅,而且它肯定不太可读…
我假设上下文类似于
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
实例可以同时存在。
除了一些智能/黑客使用不同的关键字来获得相同的行为,或添加或多或少复杂的额外模板或宏来获得unless()
关键字或以某种方式设法注入!
操作符,我坚持只做基本的事情。
这是我(可能)注入额外的"不必要的"括号的地方之一:
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关键字被意外删除"。
在你添加了重复的例子之后,我又有了一个想法。您可以尝试脚本语言中已知的技巧,其中&&
和||
可能返回非bool值:
State s = loadFoobar(&loadPointer, &results);
s = s || loadBaz(&loadPointer, &results);
s = s || loadBuz(&loadPointer, &results);
if(!s) return s;
然而,有一个问题:与脚本语言相比,在c++中,&&
和||
的重载失去了它们的短路语义,这使得这种尝试毫无意义。
然而,正如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;
}
- 我的简单if-else语句是如何无法访问的代码
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- 如何删除peer if else分支中的冗长句子
- 无法理解此 return 语句的功能,没有它就会发生运行时错误
- 我似乎对if/else的基本语句有问题:/
- 使用if-else将数字转换为单词
- c++ std::enable_if .... else?
- 如果 else 语句不断循环
- 为什么这个案例陈述需要一个"if else"而不仅仅是一个"if"?
- C++ If/Else 语句被跳过
- C++函数中的精确"return"矩
- 为什么我的最后一个 ELSE 条件无法正确执行
- '[](std::list& list)<int>{return std::move(list)}(list)' 是否保证将 'list' 留空?
- 如果条件不相关,我应该更喜欢两个 if 语句而不是 if-else 语句吗?
- 如何将 if else 语句重写为 switch 语句
- 在 C++ 中的 if-else if- else 语句期间更改变量
- 为什么我不能在我的三元表达式中使用 return,但我可以在常规的 if-else 语句中使用?
- 我是否应该将最后一个“返回”语句封装为“else { return .. }',如果它在逻辑上是可选的
- 为什么我们使用if,else-if而不是多个if块,如果主体是一个return语句
- 优雅的"if(T t = ...) { } else return t;"方式?