std::expected::operator==
的文档,显然它对 SFINAE 不友好。它不是“如果[类型不可比较],则不参与重载决策”,而是说“[在这种情况下]程序格式不正确”。
确实:
#include <concepts>
#include <expected>
struct A {};
static_assert(!std::equality_comparable<std::expected<A, A>>);
此断言在 MSVC 和带有 libc++ 的 Clang 上失败,并在带有 MSVC STL 的 Clang 上导致硬错误。
但是为什么它对 SFINAE 不友好?
无论如何,std::expected<T,U>
都需要 T
和 U
都完成,因此似乎没有什么可以阻止对其进行的所有操作都是 SFINAE 友好的。
我认为这只是被忽视了。
直到 2024 年 4 月,类似库类型的
operator==
(如 std::pair
、std::tuple
、std::optional
、std::variant
等)在这个意义上也不是 SFINAE 友好的。
它们通过 P2944R3 变得对 SFINAE 友好,这也指出这可能只是在没有任何意图的情况下发生的。
从这里开始的文件中列出了措辞的变化。如果一个子句最初表示“Mandates:”,则意味着如果不满足条件,则程序格式错误(即硬错误)。如果它最初说“先决条件:”,那么不满足条件会导致程序出现未定义的行为。当它现在显示“Constraints:”时,不满足条件意味着重载不参与重载决策(即它是 SFINAE 友好的)。
我的猜测是
std::expected
同样被遗忘了。