首页 > 解决方案 > Clang LLVM C++ `std::optional>` 令人惊讶的比较行为

问题描述

我有一个函数load(std::optional<int> page)可以加载给定页面或所有页面,如果page.empty(). 因为加载是一项昂贵的操作,所以我缓存了最后加载的页面及其内容。为此,我使用了一个类型的成员变量,std::optional<std::optional<int>>其值应该告诉我当前是否缓存了单个页面、所有页面或根本没有页面。

LLVM 的 libc++ 实现(随 clang 提供Apple LLVM version 10.0.0 (clang-1000.11.45.2))在比较 std::optional 实例时有一个令人惊讶的行为,这与它的不同boost::optional(用 1.67 测试):

std::cout << (std::optional<int>() == std::optional<std::optional<int>>()); // prints 1
std::cout << (boost::optional<int>() == boost::optional<boost::optional<int>>()); // prints 0

哪个是正确的行为,这是 libc++ 实现中的错误吗?

标签: c++c++17clang++

解决方案


行为是正确的:

https://en.cppreference.com/w/cpp/utility/optional/operator_cmp

template< class T, class U > 
constexpr bool operator!=( const optional<T>& lhs, const optional<U>& rhs ); (2)

对可选对象执行比较操作。

1-6) 比较两个可选对象 lhs 和 rhs。仅当 lhs 和 rhs 都包含值时,才比较包含的值(使用 T 的相应运算符)。否则,

  • 当且仅当 lhs 和 rhs 都不包含值时,才认为 lhs 等于 rhs。

的默认构造函数std::optional<T>构造一个不包含值的对象,因此两者std::optional<int>>()std::optional<std::optional<int>>()不包含值,因此它们是相等的。


推荐阅读