From 75272d5c1299db93aa619fc9e616832f578726c2 Mon Sep 17 00:00:00 2001 From: Jakub Kuderski Date: Tue, 21 Feb 2023 13:05:01 -0500 Subject: [PATCH] [ADT] Relax type requirements for `is_contained` - Do not require both the `Set` and `Element` to be exactly the same type and, instead, only require them to be comparable. - Do not require `Element` to be copyable. - Add missing documentation comment. Reviewed By: beanz Differential Revision: https://reviews.llvm.org/D144416 --- llvm/include/llvm/ADT/STLExtras.h | 10 ++++++---- llvm/unittests/ADT/STLExtrasTest.cpp | 19 ++++++++++++++++++- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h index 79b1456..a5cb73d 100644 --- a/llvm/include/llvm/ADT/STLExtras.h +++ b/llvm/include/llvm/ADT/STLExtras.h @@ -1870,11 +1870,13 @@ bool is_contained(R &&Range, const E &Element) { return std::find(adl_begin(Range), adl_end(Range), Element) != adl_end(Range); } -template -constexpr bool is_contained(std::initializer_list Set, T Value) { +/// Returns true iff \p Element exists in \p Set. This overload takes \p Set as +/// an initializer list and is `constexpr`-friendly. +template +constexpr bool is_contained(std::initializer_list Set, const E &Element) { // TODO: Use std::find when we switch to C++20. - for (T V : Set) - if (V == Value) + for (const T &V : Set) + if (V == Element) return true; return false; } diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp b/llvm/unittests/ADT/STLExtrasTest.cpp index 4a9c745..4c31b4f 100644 --- a/llvm/unittests/ADT/STLExtrasTest.cpp +++ b/llvm/unittests/ADT/STLExtrasTest.cpp @@ -947,11 +947,28 @@ enum Doggos { Longboi, }; +struct WooferCmp { + // Not copyable. + WooferCmp(const WooferCmp &) = delete; + WooferCmp &operator=(const WooferCmp &) = delete; + + friend bool operator==(const Doggos &Doggo, const WooferCmp &) { + return Doggo == Doggos::Woofer; + } +}; + TEST(STLExtrasTest, IsContainedInitializerList) { EXPECT_TRUE(is_contained({Woofer, SubWoofer}, Woofer)); EXPECT_TRUE(is_contained({Woofer, SubWoofer}, SubWoofer)); EXPECT_FALSE(is_contained({Woofer, SubWoofer}, Pupper)); - EXPECT_FALSE(is_contained({}, Longboi)); + + // Check that the initializer list type and the element type do not have to + // match exactly. + EXPECT_TRUE(is_contained({Floofer, Woofer, SubWoofer}, WooferCmp{})); + EXPECT_FALSE(is_contained({Floofer, SubWoofer}, WooferCmp{})); + + EXPECT_TRUE(is_contained({"a", "bb", "ccc", "dddd"}, llvm::StringRef("ccc"))); + EXPECT_FALSE(is_contained({"a", "bb", "ccc", "dddd"}, llvm::StringRef("x"))); static_assert(is_contained({Woofer, SubWoofer}, SubWoofer), "SubWoofer!"); static_assert(!is_contained({Woofer, SubWoofer}, Pupper), "Missing Pupper!"); -- 2.7.4