要防呆,它需要:哪个C++功能可以确保从选项<T>中提取T&T?
- 清晰的语法
- 可能使用
auto
- 原子的使用,以防止意外的失误像
if (!opt) { opt->call(); }
- 没有运行时断言(编辑 :和例外)
- 无编译器警告
- (可选)无静态检查器警告GS
到目前为止,我已经试过这4个选项(假设具有可变optional<T> opt;
):
选项0标准用法
if (opt) {
opt->call();
}
- +清洁代码
- +自然控制流量,有
else
声明 - -不是原子
- -
operator->
在可空类型被暴露,所以很容易调用opt->call()
无if
检查
选项1.创建一个智能指针almost_present<T>
与_DEBUG
-只有字段mutable boolean checkedPresent
设置为true
当用户确实operator bool
:
if (almost_present<T> nonull = opt.if_present()) {
// `operator->()` and `operator T&()` assert if called without doing `if (nonull)`
nonull->call();
T& x = nonull;
}
- +自然控制流程,具有
else
声明 - +将断言,如果用户没有引用之前检查值,即使它是目前
- -运行时检查
- -
almost_present<T>::operator bool() const
必须修改checkedPresent
字段 - -可能会意外地在
else
分支使用nonull
,但这是次要的
选项2。范围为基础的循环招从http://loungecpp.net/cpp/abusing-range-for/:optional<T>
或optional<T>::if_present()
实现方法begin()
和end()
看起来像0或1项
for (auto& nonull : opt.if_present()) {
nonull.call();
}
- +集合简洁的语法
- -无条件
return
在任何回路内产生warning C4702: unrechable code
(VC2017) - -没有
else
声明,必须单独调用if (!opt)
,这不是原子 - -看起来像一个循环,可能会误解,如果
T
是一家集
选项3 Lambda表达式
opt.if_present([](auto& nonull) { nonull.call(); });
auto result = opt.map(
[](auto& nonull) { return nonull.call(); },
[]() { return what_if_null(); }
);
- +它的工作原理
- -没有一个清晰的语法 - 难以阅读和调试
现在,我使用的组合 “for” 循环和 “lambda表达式”
几乎目前看起来对我来说是可选的。 – Yakk
除了娱乐之外,我不会使用.2和.3。这种代码有效地混淆了。 – Pavel
@Yakk,'almost_present'如果您忘记了'if',则会预防性地断言,所以用1个测试覆盖此代码就足够了。而'std :: optional'只会在你传递一个空值时失败,这可能非常少见。 –