std::optional 的不明确运算符重载?

Vah*_*agn 3 c++ gcc operator-overloading optional c++17

考虑这个代码。

struct Test : public std::optional<int>  { };

Test o1, o2;
o1 == o2;
Run Code Online (Sandbox Code Playgroud)

对于最后一行gcc-7.0.1抱怨error: ambiguous overload指向两个重载来比较一个可选项和一个值。但它不应该只是选择带有两个选项的重载并成功编译代码吗?


编辑 值比较的重载不应该有“守卫”禁止它们为从 std::optional 继承的类型实例化吗?

Bar*_*rry 5

可以为这个表达式找到三个重载:

// #1, with T=int, U=int
template <class T, class U> 
constexpr bool operator==(optional<T> const&, optional<U> const& );

// #2, with T=int, U=Test
template <class T, class U> 
constexpr bool operator==(optional<T> const&, U const& );

// #3, with T=int, U=Test
template <class T, class U> 
constexpr bool operator==(U const&, optional<T> const& );
Run Code Online (Sandbox Code Playgroud)

#2并且#3具有更好的转换序列,#1因为其中一个参数 (the U const&) 是 Exact Match forTest而不是 Derived-to-Base 转换。

但是,虽然我们可以更喜欢#2#3to #1,但没有理由更喜欢其中一个#2#3另一个 - 每个参数在一个参数中有更好的转换序列,而在第二个参数中有更差的转换序列。

因此,这是模棱两可的。请注意#2#3都是格式良好的运算符,因为您确实可以将 anint与 a进行比较Test。为了消除歧义,您必须另外添加一个U不继承自的约束optional<T>,这是……一个非常具体的约束。


您可以通过铸造一种或另一种解决这个Testoptional<int>,或者干脆提供optional==(Test, Test)

  • 我认为问题(请参阅问题中的 EDIT)不是为什么这些重载是模棱两可的,而是为什么委员会没有选择一组不同的重载(与某些 enable_if 相同?)不会模棱两可。 (2认同)