Clang LLVM C++ `std::optional<std::optional<int>>` 令人惊讶的比较行为

Ste*_*nev 3 c++ clang++ c++17

我有一个函数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
Run Code Online (Sandbox Code Playgroud)

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

bol*_*lov 5

行为是正确的:

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)
Run Code Online (Sandbox Code Playgroud)

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

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

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

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