c++ - 继承的综合比较运算符产生警告/错误:ISO C++20 考虑使用重载运算符 '!='
问题描述
在以下代码片段中,clang 11.0.1 生成警告
template <class T>
struct iterator_facade
{
template<class S>
bool operator==(const S &other) const noexcept
{
return static_cast<const T &>(*this).equal_to(other);
}
};
struct iterator : public iterator_facade<iterator>
{
bool equal_to(const iterator &) const noexcept
{
return true;
}
};
bool check(iterator a, iterator b)
{
return a == b;
}
实时代码: https ://godbolt.org/z/65zWEq
source>:21:14: warning: ISO C++20 considers use of overloaded operator '==' (with operand types 'iterator' and 'iterator') to be ambiguous despite there being a unique best viable function [-Wambiguous-reversed-operator]
return a == b;
~ ^ ~
<source>:5:7: note: ambiguity is between a regular call to this operator and a call with the argument order reversed
bool operator==(const S &other) const noexcept
^
上面的代码可以使用 Visual C++ (VS 16.8.x) 和以前的预览版 (VS 16.9.0 Preview 2) 成功编译。但是,最近发布的 VS 16.9.0 Preview 3 现在会为此代码片段产生错误:
1>C:\MyProjects\test\test\source.cpp(21,16): error C2666: 'foo<bar>::operator ==': 2 overloads have similar conversions
1>C:\MyProjects\test\test\source.cpp(5,7): message : could be 'bool iterator_facade<iterator>::operator ==<bar>(const S &) noexcept const' [rewritten expression '!(x == y)']
1> with
1> [
1> S=iterator
1> ]
1>C:\MyProjects\test\test\source.cpp(5,7): message : or 'bool iterator_facade<iterator>::operator ==<iterator>(const S &) noexcept const' [synthesized expression '!(y == x)']
1> with
1> [
1> S=iterator
1> ]
1>C:\MyProjects\test\test\source.cpp(21,16): message : while trying to match the argument list '(iterator, iterator)'
看起来没有为iterator
具有 CRTP 类的派生类提供综合比较运算符的合规方法iterator_facade
吗?
解决方案
问题是我们有这个比较运算符:
template<class T>
struct iterator_facade
{
template <class S>
bool operator==(const S &other) const noexcept;
};
因此,当我们尝试比较两个iterator
s 时,我们有这两个候选者:
bool operator==(iterator_facade<iterator> const&, iterator const&); // the member candidate
bool operator==(iterator const&, iterator_facade<iterator> const&); // the reversed member candidate
问题是成员候选者在第二个参数中是完全匹配的,但在第一对中是派生到基础的转换......而反转的候选者是第一个参数中的完全匹配,但是是派生到基础第二次转换。这意味着没有一个候选人比另一个更好,而且两者都是模棱两可的。
现在,由于这个库实际上需要 C++20 开始,这有点毫无意义。只需自己制作iterator
工具operator==
,这会增加......什么都没有?无论如何,我不确定它添加了什么。
但是如果你真的想让它工作,你需要提供第二个重载,它需要两个派生实例。如:
template <class T>
struct iterator_facade
{
friend bool operator==(T const& a, T const& b) noexcept {
return a.equal_to(b);
}
template <sentinel_for<T> S>
bool operator==(S const& other) const noexcept;
};
同质算子将比异质算子更好地匹配,因此比较会编译得很好。
推荐阅读
- acumatica - 尝试生成报告 PDF 时来自 Acumatica 代码的空引用异常
- android-studio - Android Studio 3.6 - 如何在 Design Palette 中使用布局?
- regex - 如何编写一个包含 1801-1899(包括 1801 和 1899)的所有值的正则表达式?
- node.js - Node.js Google PubSub 订阅者未收到某些消息
- python - 无法在 Selenium (Python) 中定位元素
- python - 在 scipy 中生成大型稀疏矩阵时在 long_scalars 中遇到溢出
- r - 如何在 RStudio 中找到特定日期阳性病例最多的州?
- javascript - 将数据推送到for循环内的数组中
- python - TypeError:float() 参数必须是字符串或数字,而不是“类型”
- regex - 如何使用 sed、awk、grep 等在跨多个文件的行的子字符串中用 %20 替换空格