Skip to content

Commit

Permalink
[ADT] Relax type requirements for is_contained
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
kuhar committed Feb 21, 2023
1 parent 9168c98 commit 75272d5
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 5 deletions.
10 changes: 6 additions & 4 deletions llvm/include/llvm/ADT/STLExtras.h
Expand Up @@ -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 <typename T>
constexpr bool is_contained(std::initializer_list<T> 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 <typename T, typename E>
constexpr bool is_contained(std::initializer_list<T> 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;
}
Expand Down
19 changes: 18 additions & 1 deletion llvm/unittests/ADT/STLExtrasTest.cpp
Expand Up @@ -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!");
Expand Down

0 comments on commit 75272d5

Please sign in to comment.