为啥 std::optional operator* 没有 has_value() 的调试模式断言?

Posted

技术标签:

【中文标题】为啥 std::optional operator* 没有 has_value() 的调试模式断言?【英文标题】:Why does std::optional operator* not have debug mode assertion for has_value()?为什么 std::optional operator* 没有 has_value() 的调试模式断言? 【发布时间】:2019-09-07 16:35:43 【问题描述】:

我完全理解由于性能原因,std::optional 中的operator* 不会对包含值的实际存在进行任何检查。但是,在调试模式下,性能考虑应该无关紧要,在调试模式下应该做出某种断言对我来说很有意义。

Visual Studio 似乎没有这样的断言(尽管我不确定其他编译器)。

我的问题是:编译器不会在调试模式下做出这样的断言是否有任何根本原因,或者它只是一个缺失的功能?

【问题讨论】:

调试版本与发布版本的差异越大,它的用处就越小。 【参考方案1】:

编译器在调试模式下不会做出这样的断言是否有任何根本原因,或者它只是一个缺失的功能?

ODR 违规。 std::optional 是一个类模板,因此在标题中实现。不同预处理器符号的标头内代码的不同行为是危险的。考虑这个例子(未经测试,你会明白的):

clang++ -DNDEBUG usesOptionalOfInt.cpp -shared -c -o myLib.so
clang++ alsoUsesOptionalOfInt.cpp main.cpp -lmyLib -o ./ub-please

你去与未定义的行为。请注意,std::optional::operator* 中的差异实际上不太可能在此示例中造成任何伤害,但您仍然希望避免这些情况。

【讨论】:

但是,如果要在静态库上使用 STL,则无论如何都必须使用相同的编译器选项构建它们,否则将无济于事! std::vector 已经在 Visual Studio 中充满了断言(请参阅各种 _ITERATOR_DEBUG_LEVELs 下的 _STL_VERIFY() )。这些断言与@FranciscoMartinez 提出的断言有什么区别? 这些是保留名称 - 不允许客户端代码与这些混淆。来自cppreference:“以下划线后跟大写字母的标识符被保留”。这是与例如的主要区别。 NDEBUG 宏。

以上是关于为啥 std::optional operator* 没有 has_value() 的调试模式断言?的主要内容,如果未能解决你的问题,请参考以下文章

为啥允许将 std::optional 与值进行比较? [复制]

为啥 std::optional 构造函数使用 std::in_place?

为啥 std::optional::value() &&;返回 &&?

为啥 const rvalue 限定 std::optional::value() 返回 const rvalue 引用?

为啥 std::optional 对 std::nullopt 类型的操作数有一个特殊的相等运算符

为啥 std::optional 不允许“移动构造和仅复制分配”类型的移动分配?