[STLExtras] Add a template for detecting whether a type has an equality comparison operator#176429
Conversation
…ty-comparison operator
|
@llvm/pr-subscribers-llvm-adt Author: Benjamin Stott (BStott6) ChangesThis is needed for #173026. Full diff: https://github.com/llvm/llvm-project/pull/176429.diff 2 Files Affected:
diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h
index 23da931a63de1..fd31430ede911 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>
+using has_equality_comparison =
+ decltype(std::declval<const T &>() == std::declval<const T &>());
+} // namespace detail
+
+/// Detects when type `const T` can be compared for equality with itself.
+template <typename T>
+constexpr bool has_equality_comparison_v =
+ is_detected<detail::has_equality_comparison, T>::value;
} // end namespace llvm
namespace std {
diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp b/llvm/unittests/ADT/STLExtrasTest.cpp
index fe71945e4a794..02b4eee04d005 100644
--- a/llvm/unittests/ADT/STLExtrasTest.cpp
+++ b/llvm/unittests/ADT/STLExtrasTest.cpp
@@ -1780,6 +1780,28 @@ struct Bar {};
static_assert(is_incomplete_v<Foo>, "Foo is incomplete");
static_assert(!is_incomplete_v<Bar>, "Bar is defined");
+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 PrivateEqualityComparison {
+private:
+ bool operator==(const PrivateEqualityComparison &Other) const {
+ return false;
+ }
+};
+static_assert(!has_equality_comparison_v<PrivateEqualityComparison>);
+
+struct PublicEqualityComparison {
+ bool operator==(const PublicEqualityComparison &Other) const { return false; }
+};
+static_assert(has_equality_comparison_v<PublicEqualityComparison>);
+
TEST(STLExtrasTest, Search) {
// Test finding a subsequence in the middle.
std::vector<int> Haystack = {1, 2, 3, 4, 5, 6, 7, 8};
|
|
Thanks! And thank you kuhar for the tips |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/2/builds/42388 Here is the relevant piece of the build log for the reference |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/46/builds/29318 Here is the relevant piece of the build log for the reference |
…n be compared for equality (#176429)" This reverts commit a66b8b7. MSVC doesn't like it: https://lab.llvm.org/buildbot/#/builders/2/builds/42388/steps/7/logs/stdio Thus we'll revert and examine that.
|
Apparently MSVC doesn't like this assertion: (https://lab.llvm.org/buildbot/#/builders/2/builds/42388/steps/7/logs/stdio) I think we should drop it and re-land. |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/108/builds/22038 Here is the relevant piece of the build log for the reference |
…n equality comparison operator" (#176893) This PR is an attempt to reland #176429. It seems there's a difference between Clang and MSVC's template handling, resulting in a difference in the behaviour of is_detected with private class members. [This](https://godbolt.org/z/x61YdEz44) Godbolt link demonstrates the difference. This was causing one of the test cases I made, which was checking that it didn't pick up a private equality comparison operator, to fail when compiled using MSVC. In this PR I have just removed that test case.
… type has an equality comparison operator" (#176893) This PR is an attempt to reland llvm/llvm-project#176429. It seems there's a difference between Clang and MSVC's template handling, resulting in a difference in the behaviour of is_detected with private class members. [This](https://godbolt.org/z/x61YdEz44) Godbolt link demonstrates the difference. This was causing one of the test cases I made, which was checking that it didn't pick up a private equality comparison operator, to fail when compiled using MSVC. In this PR I have just removed that test case.
…s an equality comparison operator" (#177415) Reland PR #176893 which was an attempt to reland PR #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.
…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 is needed for #173026.