【发布时间】:2021-04-26 04:53:40
【问题描述】:
在下面的代码中 sn -p 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 现在会为此代码 sn-p 产生错误:
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 提供综合比较运算符?
【问题讨论】:
-
综合运算符的全部意义在于它很容易做到,您不需要在基类中进行。只需给
bar一个与equal_to完全相同的operator==重载就可以了。 -
这个例子无论如何都不会在 C++17 中编译。你有一个更完整的例子来说明你的想法吗?
foo也应该支持异构比较,还是只支持同质比较? -
这里是以下
iterator_facade实现的简化:https://github.com/vector-of-bool/neo-fun/blob/develop/src/neo/iterator_facade.hpp 该类的重点是在基类中实现这些运算符:) -
这个迭代器外观类尝试通过派生类的
equal_to或distance_to成员(无论哪个可用)来实现所需的迭代器比较运算符。旧版本通过实现通常的 ==、!= 等来实现。一段时间后,作者改用 C++20 综合运算符,简化了代码。它曾经一直工作到 VS 16.9.0 Preview 3。它开始产生一个错误,我将其简化为上面的代码 sn-p。
标签: c++ c++20 spaceship-operator