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& );