Vector: C++20 equality operators

Problem:
- C++20 changes the way equality operators are generated. This results
  in overload ambiguity as reported by clang.

Solution:
- Remove `AK::Vector::operator!=` because it will be automatically
  generated in terms of `AK::Vector::operator==`.
- Change `AK::Vector::operator==` to be a function template so that
  overload resolution is not confused about `a == b` vs `b == a`.
- Add tests to ensure the behavior works.

Notes:
- There is more info available at
  https://brevzin.github.io/c++/2019/07/28/comparisons-cpp20/ for
  deeper discussion about overload resolution, operator rewriting, and
  generated functions.
This commit is contained in:
Lenny Maiorani 2020-11-15 09:45:53 -07:00 committed by Andreas Kling
parent 3c64cec4d7
commit 2a06b026ef
2 changed files with 72 additions and 7 deletions

View file

@ -327,4 +327,71 @@ TEST_CASE(resize_initializes)
EXPECT(ints[idx].initialized);
}
TEST_CASE(should_compare_vectors_of_same_type)
{
Vector<int> a {};
Vector<int> b {};
EXPECT(a == b);
EXPECT(!(a != b));
a.append(1);
EXPECT(!(a == b));
EXPECT(a != b);
b.append(1);
EXPECT(a == b);
EXPECT(!(a != b));
a.append(42);
b.append(17);
EXPECT(!(a == b));
EXPECT(a != b);
}
TEST_CASE(should_compare_vectors_of_different_inline_capacity)
{
Vector<int, 1> a {};
Vector<int, 64> b {};
EXPECT(a == b);
EXPECT(!(a != b));
a.append(1);
EXPECT(!(a == b));
EXPECT(a != b);
b.append(1);
EXPECT(a == b);
EXPECT(!(a != b));
a.append(42);
b.append(17);
EXPECT(!(a == b));
EXPECT(a != b);
}
TEST_CASE(should_compare_vectors_of_different_sizes)
{
Vector<int, 0> a {};
Vector<int, 0> b {};
EXPECT(a == b);
EXPECT(!(a != b));
// A is longer
a.append(1);
EXPECT(!(a == b));
EXPECT(a != b);
b.append(1);
EXPECT(a == b);
EXPECT(!(a != b));
// B is longer
b.append(42);
EXPECT(!(a == b));
EXPECT(a != b);
}
TEST_MAIN(Vector)

View file

@ -52,6 +52,8 @@ namespace AK {
template<typename T, size_t inline_capacity>
class Vector {
public:
using value_type = T;
Vector()
: m_capacity(inline_capacity)
{
@ -147,18 +149,14 @@ public:
m_size = 0;
}
bool operator==(const Vector& other) const
template<typename V>
bool operator==(const V& other) const
{
if (m_size != other.m_size)
if (m_size != other.size())
return false;
return TypedTransfer<T>::compare(data(), other.data(), size());
}
bool operator!=(const Vector& other) const
{
return !(*this == other);
}
operator Span<T>() { return span(); }
operator Span<const T>() const { return span(); }