Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions llvm/include/llvm/ADT/STLExtras.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,14 @@ template <typename ContainerTy> bool hasSingleElement(ContainerTy &&C) {
return B != E && std::next(B) == E;
}

/// Asserts that the given container has a single element and returns that
/// element.
template <typename ContainerTy>
decltype(auto) getSingleElement(ContainerTy &&C) {
assert(hasSingleElement(C) && "expected container with single element");
return *adl_begin(C);
}

/// Return a range covering \p RangeOrContainer with the first N elements
/// excluded.
template <typename T> auto drop_begin(T &&RangeOrContainer, size_t N = 1) {
Expand Down
34 changes: 34 additions & 0 deletions llvm/unittests/ADT/STLExtrasTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,40 @@ TEST(STLExtrasTest, hasSingleElement) {
EXPECT_FALSE(hasSingleElement(S));
}

TEST(STLExtrasTest, getSingleElement) {
// Test const and non-const containers.
const std::vector<int> V1 = {7};
EXPECT_EQ(getSingleElement(V1), 7);
std::vector<int> V2 = {8};
EXPECT_EQ(getSingleElement(V2), 8);

// Test LLVM container.
SmallVector<int> V3{9};
EXPECT_EQ(getSingleElement(V3), 9);

// Test that the returned element is a reference.
getSingleElement(V3) = 11;
EXPECT_EQ(V3[0], 11);

// Test non-random access container.
std::list<int> L1 = {10};
EXPECT_EQ(getSingleElement(L1), 10);

// Make sure that we use the `begin`/`end` functions from `some_namespace`,
// using ADL.
some_namespace::some_struct S;
S.data = V2;
EXPECT_EQ(getSingleElement(S), 8);

// Make sure that we crash on empty or too many elements.
SmallVector<int> V4;
EXPECT_DEATH(getSingleElement(V4), "expected container with single element");
SmallVector<int> V5{12, 13, 14};
EXPECT_DEATH(getSingleElement(V5), "expected container with single element");
std::list<int> L2;
EXPECT_DEATH(getSingleElement(L2), "expected container with single element");
}

TEST(STLExtrasTest, hasNItems) {
const std::list<int> V0 = {}, V1 = {1}, V2 = {1, 2};
const std::list<int> V3 = {1, 3, 5};
Expand Down
Loading