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

C++ std::optional的运算符重载不明确?,c++,gcc,operator-overloading,optional,c++17,C++,Gcc,Operator Overloading,Optional,C++17,以代码为例 struct-Test:public-std::optional{}; 试验o1、o2; o1==o2; 最后一行gcc-7.0.1抱怨错误:不明确的重载指向两个重载,用于将可选值与值进行比较。但是,难道它不应该用两个选项选择重载并成功编译代码吗 编辑 值比较的重载不应该有“保护”来禁止它们为从std::optional继承的类型实例化吗?此表达式有三个重载: // #1, with T=int, U=int template <class T, class U>

以代码为例

struct-Test:public-std::optional{};
试验o1、o2;
o1==o2;
最后一行
gcc-7.0.1
抱怨
错误:不明确的重载
指向两个重载,用于将可选值与值进行比较。但是,难道它不应该用两个选项选择重载并成功编译代码吗


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

此表达式有三个重载:

// #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& );
/#1,其中T=int,U=int
模板
constexpr bool运算符==(可选const&,可选const&);
//#2,T=int,U=Test
模板
constexpr bool运算符==(可选const&,U const&);
//#3,T=int,U=Test
模板
constexpr bool运算符==(U常量&,可选常量&);
#2
#3
#1
具有更好的转换顺序,因为其中一个参数(
U常量&
)与
测试
完全匹配,而不是派生到基的转换

但是,虽然我们可以更喜欢
#2
#3
而不是
#1
,但没有理由更喜欢
#2
#3
中的一个,因为它们在一个参数中的转换顺序更好,在第二个参数中的转换顺序更差

因此,它是模棱两可的。注意
#2
#3
都是格式良好的运算符,因为您确实可以将
int
测试进行比较。为了消除歧义,您必须另外添加一个约束,
U
不继承自
optional
,即。。。一个非常具体的约束



您可以通过将一个或另一个
Test
转换为
optional
,或者简单地提供一个
optional==(Test,Test)

一个更好的问题是,您为什么要继承
optional
,为了给它添加一些额外的语义负载,创建私有成员可能是另一种选择,但这是一种更糟糕的选择,因为我需要
std::optional
提供的所有功能,另外我正在添加一些更多的功能。我不想重新定义reset()、emplace()等。最终我添加了
optional==(Test,Test)
,但在库透视图中,不应该更喜欢从std::optional派生的类而不是这些重载的值吗?我想问题(请参见问题中的编辑)不是为什么这些重载不明确,但是更多的原因是为什么委员会没有选择一组不同的重载(一些enable_if?)这一点并不含糊。@marglisse一组额外的重载专门用于
U
继承自
optional
?我没有说这是个好主意,但我就是这样解释这个问题的。@Barry Yes,如果
U
继承自
可选
,或可转换为
可选
,则需要额外的一组重载。
// #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& );