-
Notifications
You must be signed in to change notification settings - Fork 11.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[libc][cpp] reverse_iterator support (#85702)
Towards the goal of implementing __cxa_finalize (#85651) I'd like to be able to reverse iterate over cpp::arrays such as the one used in FixedVector. Implement the enough iterator support to be able to iterate a cpp::array in reverse, and add tests. Of note, reverse iterator's begin() refers to forward iterator's end() (and vice versa). When dereferenced (operator*), the reverse iterator returns a copy that's been pre-decremented (the underlying forward iterator is advanced).
- Loading branch information
1 parent
252e255
commit c63a291
Showing
4 changed files
with
162 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
//===-- Standalone implementation of iterator -------------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_ITERATOR_H | ||
#define LLVM_LIBC_SRC___SUPPORT_CPP_ITERATOR_H | ||
|
||
#include "src/__support/CPP/type_traits/enable_if.h" | ||
#include "src/__support/CPP/type_traits/is_convertible.h" | ||
#include "src/__support/CPP/type_traits/is_same.h" | ||
#include "src/__support/macros/attributes.h" | ||
|
||
namespace LIBC_NAMESPACE { | ||
namespace cpp { | ||
|
||
template <typename T> struct iterator_traits; | ||
template <typename T> struct iterator_traits<T *> { | ||
using reference = T &; | ||
}; | ||
|
||
template <typename Iter> class reverse_iterator { | ||
Iter current; | ||
|
||
public: | ||
using reference = typename iterator_traits<Iter>::reference; | ||
|
||
LIBC_INLINE reverse_iterator() : current() {} | ||
LIBC_INLINE constexpr explicit reverse_iterator(Iter it) : current(it) {} | ||
|
||
template <typename Other, | ||
cpp::enable_if_t<!cpp::is_same_v<Iter, Other> && | ||
cpp::is_convertible_v<const Other &, Iter>, | ||
int> = 0> | ||
LIBC_INLINE constexpr explicit reverse_iterator(const Other &it) | ||
: current(it) {} | ||
|
||
LIBC_INLINE constexpr reference operator*() const { | ||
Iter tmp = current; | ||
return *--tmp; | ||
} | ||
LIBC_INLINE constexpr reverse_iterator operator--() { | ||
++current; | ||
return *this; | ||
} | ||
LIBC_INLINE constexpr reverse_iterator &operator++() { | ||
--current; | ||
return *this; | ||
} | ||
LIBC_INLINE constexpr reverse_iterator operator++(int) { | ||
reverse_iterator tmp(*this); | ||
--current; | ||
return tmp; | ||
} | ||
}; | ||
|
||
} // namespace cpp | ||
} // namespace LIBC_NAMESPACE | ||
|
||
#endif // LLVM_LIBC_SRC___SUPPORT_CPP_ITERATOR_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
//===-- Unittests for Array -----------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "src/__support/CPP/array.h" | ||
#include "test/UnitTest/Test.h" | ||
|
||
using LIBC_NAMESPACE::cpp::array; | ||
|
||
TEST(LlvmLibcArrayTest, Basic) { | ||
array<int, 3> a = {0, 1, 2}; | ||
|
||
ASSERT_EQ(a.data(), &a.front()); | ||
ASSERT_EQ(a.front(), 0); | ||
ASSERT_EQ(a.back(), 2); | ||
ASSERT_EQ(a.size(), size_t{3}); | ||
ASSERT_EQ(a[1], 1); | ||
ASSERT_FALSE(a.empty()); | ||
ASSERT_NE(a.begin(), a.end()); | ||
ASSERT_EQ(*a.begin(), a.front()); | ||
|
||
auto it = a.rbegin(); | ||
ASSERT_EQ(*it, 2); | ||
ASSERT_EQ(*(++it), 1); | ||
ASSERT_EQ(*(++it), 0); | ||
|
||
for (int &x : a) | ||
ASSERT_GE(x, 0); | ||
} | ||
|
||
// Test const_iterator and const variant methods. | ||
TEST(LlvmLibcArrayTest, Const) { | ||
const array<int, 3> z = {3, 4, 5}; | ||
|
||
ASSERT_EQ(3, z.front()); | ||
ASSERT_EQ(4, z[1]); | ||
ASSERT_EQ(5, z.back()); | ||
ASSERT_EQ(3, *z.data()); | ||
|
||
// begin, cbegin, end, cend | ||
array<int, 3>::const_iterator it2 = z.begin(); | ||
ASSERT_EQ(*it2, z.front()); | ||
it2 = z.cbegin(); | ||
ASSERT_EQ(*it2, z.front()); | ||
it2 = z.end(); | ||
ASSERT_NE(it2, z.begin()); | ||
it2 = z.cend(); | ||
ASSERT_NE(it2, z.begin()); | ||
|
||
// rbegin, crbegin, rend, crend | ||
array<int, 3>::const_reverse_iterator it = z.rbegin(); | ||
ASSERT_EQ(*it, z.back()); | ||
it = z.crbegin(); | ||
ASSERT_EQ(*it, z.back()); | ||
it = z.rend(); | ||
ASSERT_EQ(*--it, z.front()); | ||
it = z.crend(); | ||
ASSERT_EQ(*--it, z.front()); | ||
|
||
for (const int &x : z) | ||
ASSERT_GE(x, 0); | ||
} |