2017-04-17 30 views
0

要防呆,它需要:哪个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表达式”

+0

几乎目前看起来对我来说是可选的。 – Yakk

+0

除了娱乐之外,我不会使用.2和.3。这种代码有效地混淆了。 – Pavel

+0

@Yakk,'almost_present'如果您忘记了'if',则会预防性地断言,所以用1个测试覆盖此代码就足够了。而'std :: optional '只会在你传递一个空值时失败,这可能非常少见。 –

回答

0
auto v = opt.value(); 

抛出一个bad_optional_access如果opt包含没有价值。

+0

嗯,那正是我想要避免的 - 运行时断言并抛出 –

+0

@MykolaBogdiuk你没有提到你想避免异常。 –

+0

正式的是,但我不会使用'可选的',如果我明确地知道它不是空的话。将编辑该问题。 –

相关问题