"if(T t = ...) { } else return t;" 的优雅方式?
Elegant way for "if(T t = ...) { } else return t;"?
有没有更好的方法"idiom"?
if(State s = loadSomething()) { } else return s;
换句话说,我想做一些事情,这可能 return 一个错误(带有消息)或一个成功状态,如果有错误我想 return 它。这会变得非常重复,所以我想缩短它。例如
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;
这不能使用例外情况,否则我会赞成(不适合此版本)。我可以写一些 class BooleanNegator<State>
来存储值,并否定其布尔值。但我想避免临时执行此操作,而更喜欢 boost/standard 解决方案。
你可以这样做:
for (State s = loadSomething(); !s; ) return s;
但我不确定它是否更优雅,而且它的可读性肯定更差...
我假设上下文是这样的
State SomeFunction()
{
if(State s = loadSomething()) { } else return s;
return do_something_else();
}
不抛出异常,其中 do_something_else()
做了一些与 SomeFunction()
和 returns 和 State
相关的事情。无论哪种方式,在函数内继续的结果需要导致返回 State
,因为从末尾掉下来会导致调用者表现出未定义的行为。
在那种情况下,我会简单地将函数重组为
State SomeFunction()
{
if (State s = loadSomething())
return do_something_else();
else
return s;
}
隐含的假设是 State
有一些可以测试的运算符(例如 operator bool()
),复制 State
是可能的(暗示存在 loadSomething()
returns 一个)并且相对便宜,State
的两个实例可以同时存在。
除了一些 smart/hacky 使用不同的关键字来获得相同的行为,或添加或多或少复杂的额外模板或宏来获得 unless()
关键字或以某种方式设法注入 !
操作员,我会坚持基本的东西。
这是我(可能)注入额外 "unnecessary" 括号的地方之一:
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
.
的可见性
然而,有些人 "hate" 看到 { .. }
没有加上 keyword/class/function/etc,甚至认为它不可读,因为 "suggesting that a if/while/etc keyword was accidentally deleted".
添加重复示例后,我又想到了一个主意。您可以尝试使用脚本语言中已知的技巧,其中 &&
和 ||
可能 return 一个非布尔值:
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;
}
有没有更好的方法"idiom"?
if(State s = loadSomething()) { } else return s;
换句话说,我想做一些事情,这可能 return 一个错误(带有消息)或一个成功状态,如果有错误我想 return 它。这会变得非常重复,所以我想缩短它。例如
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;
这不能使用例外情况,否则我会赞成(不适合此版本)。我可以写一些 class BooleanNegator<State>
来存储值,并否定其布尔值。但我想避免临时执行此操作,而更喜欢 boost/standard 解决方案。
你可以这样做:
for (State s = loadSomething(); !s; ) return s;
但我不确定它是否更优雅,而且它的可读性肯定更差...
我假设上下文是这样的
State SomeFunction()
{
if(State s = loadSomething()) { } else return s;
return do_something_else();
}
不抛出异常,其中 do_something_else()
做了一些与 SomeFunction()
和 returns 和 State
相关的事情。无论哪种方式,在函数内继续的结果需要导致返回 State
,因为从末尾掉下来会导致调用者表现出未定义的行为。
在那种情况下,我会简单地将函数重组为
State SomeFunction()
{
if (State s = loadSomething())
return do_something_else();
else
return s;
}
隐含的假设是 State
有一些可以测试的运算符(例如 operator bool()
),复制 State
是可能的(暗示存在 loadSomething()
returns 一个)并且相对便宜,State
的两个实例可以同时存在。
除了一些 smart/hacky 使用不同的关键字来获得相同的行为,或添加或多或少复杂的额外模板或宏来获得 unless()
关键字或以某种方式设法注入 !
操作员,我会坚持基本的东西。
这是我(可能)注入额外 "unnecessary" 括号的地方之一:
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
.
然而,有些人 "hate" 看到 { .. }
没有加上 keyword/class/function/etc,甚至认为它不可读,因为 "suggesting that a if/while/etc keyword was accidentally deleted".
添加重复示例后,我又想到了一个主意。您可以尝试使用脚本语言中已知的技巧,其中 &&
和 ||
可能 return 一个非布尔值:
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;
}