Skip to content

Commit 44d1832

Browse files
authored
Reland #2 "[STLExtras] Add a template for detecting whether a type has an equality comparison operator" (llvm#177415)
Reland PR llvm#176893 which was an attempt to reland PR llvm#176429. Fix: There was a test case asserting that for types `StructA` `StructB` where `operator==(const StructB &, const StructA &)` is defined, `has_equality_comparison_v<StructA, StructB>` is false because the arguments are the wrong way around. However, in C++20, operator overload resolution was changed so that for reflexive comparison operators `==` and `!=` if a candidate exists with the arguments swapped then this will be used. This means the test case failed when compiled with C++20. That check was simply removed in this version.
1 parent 87a8d40 commit 44d1832

2 files changed

Lines changed: 37 additions & 0 deletions

File tree

llvm/include/llvm/ADT/STLExtras.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2692,6 +2692,17 @@ template <typename T> using has_sizeof = decltype(sizeof(T));
26922692
template <typename T>
26932693
constexpr bool is_incomplete_v = !is_detected<detail::has_sizeof, T>::value;
26942694

2695+
// Detect types with equality comparison operators.
2696+
namespace detail {
2697+
template <typename T, typename U>
2698+
using has_equality_comparison =
2699+
decltype(std::declval<const T &>() == std::declval<const U &>());
2700+
} // namespace detail
2701+
2702+
/// Detects when type `const T` can be compared for equality with `const U`.
2703+
template <typename T, typename U = T>
2704+
constexpr bool has_equality_comparison_v =
2705+
is_detected<detail::has_equality_comparison, T, U>::value;
26952706
} // end namespace llvm
26962707

26972708
namespace std {

llvm/unittests/ADT/STLExtrasTest.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1807,6 +1807,32 @@ struct Bar {};
18071807
static_assert(is_incomplete_v<Foo>, "Foo is incomplete");
18081808
static_assert(!is_incomplete_v<Bar>, "Bar is defined");
18091809

1810+
TEST(STLExtrasTest, HasEqualityComparison) {
1811+
struct NoEqualityComparison {};
1812+
static_assert(!has_equality_comparison_v<NoEqualityComparison>);
1813+
1814+
// Mutating equality comparison doesn't count.
1815+
struct MutatingEqualityComparison {
1816+
bool operator==(MutatingEqualityComparison &Other) { return false; }
1817+
};
1818+
static_assert(!has_equality_comparison_v<MutatingEqualityComparison>);
1819+
1820+
struct PublicEqualityComparison {
1821+
bool operator==(const PublicEqualityComparison &Other) const {
1822+
return false;
1823+
}
1824+
};
1825+
static_assert(has_equality_comparison_v<PublicEqualityComparison>);
1826+
1827+
struct StructA {};
1828+
struct StructB {
1829+
bool operator==(const StructA &Other) const { return false; }
1830+
};
1831+
static_assert(has_equality_comparison_v<StructB, StructA>);
1832+
1833+
SUCCEED();
1834+
}
1835+
18101836
TEST(STLExtrasTest, Search) {
18111837
// Test finding a subsequence in the middle.
18121838
std::vector<int> Haystack = {1, 2, 3, 4, 5, 6, 7, 8};

0 commit comments

Comments
 (0)