Reland #2 "[STLExtras] Add a template for detecting whether a type has an equality comparison operator" - #177415
Conversation
…ty-comparison operator
…back out of that test function
|
@llvm/pr-subscribers-llvm-adt Author: Benjamin Stott (BStott6) ChangesThis PR is an attempt to reland #176893, which was an attempt to reland #176429. I had a test case asserting that for types Full diff: https://github.com/llvm/llvm-project/pull/177415.diff 2 Files Affected:
diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h
index 23da931a63de1..d9c6b9ac5f1d7 100644
--- a/llvm/include/llvm/ADT/STLExtras.h
+++ b/llvm/include/llvm/ADT/STLExtras.h
@@ -2682,6 +2682,17 @@ template <typename T> using has_sizeof = decltype(sizeof(T));
template <typename T>
constexpr bool is_incomplete_v = !is_detected<detail::has_sizeof, T>::value;
+// Detect types with equality comparison operators.
+namespace detail {
+template <typename T, typename U>
+using has_equality_comparison =
+ decltype(std::declval<const T &>() == std::declval<const U &>());
+} // namespace detail
+
+/// Detects when type `const T` can be compared for equality with `const U`.
+template <typename T, typename U = T>
+constexpr bool has_equality_comparison_v =
+ is_detected<detail::has_equality_comparison, T, U>::value;
} // end namespace llvm
namespace std {
diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp b/llvm/unittests/ADT/STLExtrasTest.cpp
index fe71945e4a794..9d905edf18eab 100644
--- a/llvm/unittests/ADT/STLExtrasTest.cpp
+++ b/llvm/unittests/ADT/STLExtrasTest.cpp
@@ -1780,6 +1780,32 @@ struct Bar {};
static_assert(is_incomplete_v<Foo>, "Foo is incomplete");
static_assert(!is_incomplete_v<Bar>, "Bar is defined");
+TEST(STLExtrasTest, HasEqualityComparison) {
+ struct NoEqualityComparison {};
+ static_assert(!has_equality_comparison_v<NoEqualityComparison>);
+
+ // Mutating equality comparison doesn't count.
+ struct MutatingEqualityComparison {
+ bool operator==(MutatingEqualityComparison &Other) { return false; }
+ };
+ static_assert(!has_equality_comparison_v<MutatingEqualityComparison>);
+
+ struct PublicEqualityComparison {
+ bool operator==(const PublicEqualityComparison &Other) const {
+ return false;
+ }
+ };
+ static_assert(has_equality_comparison_v<PublicEqualityComparison>);
+
+ struct StructA {};
+ struct StructB {
+ bool operator==(const StructA &Other) const { return false; }
+ };
+ static_assert(has_equality_comparison_v<StructB, StructA>);
+
+ SUCCEED();
+}
+
TEST(STLExtrasTest, Search) {
// Test finding a subsequence in the middle.
std::vector<int> Haystack = {1, 2, 3, 4, 5, 6, 7, 8};
|
🪟 Windows x64 Test Results
✅ The build succeeded and all tests passed. |
|
Looks like the only pre-merge failure is Merging for @BStott6 :) |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/215/builds/20758 Here is the relevant piece of the build log for the reference |
Seems unrelated |
…e 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.
…e 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.
This PR is an attempt to reland #176893, which was an attempt to reland #176429.
I had a test case asserting that for types
StructAStructBwhereoperator==(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 my test case failed when compiled with C++20. As kuhar suggested, I have just removed this assertion, but if people would prefer me to change the assertion to be conditional on the C++ version I will do it.