Skip to content

Reland #2 "[STLExtras] Add a template for detecting whether a type has an equality comparison operator" - #177415

Merged
OCHyams merged 10 commits into
llvm:mainfrom
BStott6:stlextras-equality-comparison-detection
Apr 23, 2026
Merged

Reland #2 "[STLExtras] Add a template for detecting whether a type has an equality comparison operator"#177415
OCHyams merged 10 commits into
llvm:mainfrom
BStott6:stlextras-equality-comparison-detection

Conversation

@BStott6

@BStott6 BStott6 commented Jan 22, 2026

Copy link
Copy Markdown
Contributor

This PR is an attempt to reland #176893, which was an attempt to reland #176429.

I had 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 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.

@llvmbot

llvmbot commented Jan 22, 2026

Copy link
Copy Markdown
Member

@llvm/pr-subscribers-llvm-adt

Author: Benjamin Stott (BStott6)

Changes

This PR is an attempt to reland #176893, which was an attempt to reland #176429.

I had a test case asserting that for types StructA StructB where operator==(const StructB &amp;, const StructA &amp;) is defined, has_equality_comparison_v&lt;StructA, StructB&gt; 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.


Full diff: https://github.com/llvm/llvm-project/pull/177415.diff

2 Files Affected:

  • (modified) llvm/include/llvm/ADT/STLExtras.h (+11)
  • (modified) llvm/unittests/ADT/STLExtrasTest.cpp (+26)
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};

@github-actions

github-actions Bot commented Jan 22, 2026

Copy link
Copy Markdown

🪟 Windows x64 Test Results

  • 133830 tests passed
  • 3136 tests skipped

✅ The build succeeded and all tests passed.

@OCHyams

OCHyams commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Looks like the only pre-merge failure is lldb-api :: functionalities/thread/finish-from-empty-func/TestEmptyFuncThreadStepOut.py which seems unrelated + fails on other PRs.

Merging for @BStott6 :)

@OCHyams
OCHyams merged commit 44d1832 into llvm:main Apr 23, 2026
9 of 10 checks passed
@llvm-ci

llvm-ci commented Apr 23, 2026

Copy link
Copy Markdown

LLVM Buildbot has detected a new failure on builder libc-arm32-qemu-debian-dbg running on libc-arm32-qemu-debian while building llvm at step 2 "update-annotated-scripts".

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
Step 2 (update-annotated-scripts) failure: update (failure)
git version 2.39.5
remote: Internal Server Error
fatal: unable to access 'https://github.com/llvm/llvm-zorg.git/': The requested URL returned error: 500
error: RPC failed; HTTP 500 curl 22 The requested URL returned error: 500
fatal: expected flush after ref listing

@OCHyams

OCHyams commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

LLVM Buildbot has detected a new failure on builder libc-arm32-qemu-debian-dbg running on libc-arm32-qemu-debian while building llvm at step 2 "update-annotated-scripts".

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

remote: Internal Server Error
fatal: unable to access 'https://github.com/llvm/llvm-zorg.git/': The requested URL returned error: 500

Seems unrelated

yingopq pushed a commit to yingopq/llvm-project that referenced this pull request Apr 29, 2026
…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.
KHicketts pushed a commit to KHicketts/llvm-project that referenced this pull request Apr 30, 2026
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants