Skip to content

[libcxx][test] Do not assume array::iterator is a pointer #100603

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <algorithm>
#include <array>
#include <cassert>
#include <memory>
#include <ranges>
#include <vector>

Expand Down Expand Up @@ -61,7 +62,8 @@ template <class It, class Sent = It>
constexpr void test_iterators() {
using ValueT = std::iter_value_t<It>;
auto make_range = [](auto& a) {
return std::ranges::subrange(It(std::ranges::begin(a)), Sent(It(std::ranges::end(a))));
return std::ranges::subrange(
It(std::to_address(std::ranges::begin(a))), Sent(It(std::to_address(std::ranges::end(a)))));
};
{ // simple test
{
Expand Down Expand Up @@ -91,7 +93,7 @@ constexpr void test_iterators() {
std::array<ValueT, 0> a = {};

auto ret = std::ranges::find_last(make_range(a), 1).begin();
assert(ret == It(a.begin()));
assert(ret == It(a.data()));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,14 @@ constexpr void test_iterator_classes() {
{
std::array<int, 0> a = {};

auto ret = std::ranges::find_last_if(it(a.data()), sent(it(a.data())), [](auto&&) { return true; }).begin();
assert(ret == it(a.data()));
auto ret = std::ranges::find_last_if(it(a.begin()), sent(it(a.end())), [](auto&&) { return true; }).begin();
assert(ret == it(a.end()));
}
{
std::array<int, 0> a = {};

auto ret = std::ranges::find_last_if(make_range<it, sent>(a), [](auto&&) { return true; }).begin();
assert(ret == it(a.begin()));
assert(ret == it(a.end()));
}
}

Expand Down Expand Up @@ -183,8 +183,17 @@ struct NonConstComparable {
friend constexpr bool operator==(NonConstComparable&, const NonConstComparable&) { return true; }
};

// note: this should really use `std::const_iterator`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you open an issue and change this to a TODO instead please? AIUI we're only not doing that because const_iterator isn't around yet.

Copy link
Contributor Author

@strega-nil strega-nil Jul 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I'll open an issue after merging.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I meant using the issue in the todo as TODO(<#issue-number>): <reason>.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I meant using the issue in the todo as TODO(<#issue-number>): <reason>.

This was a part of my conditional LGTM. I will make it clearer in future reviews.

template <class T>
using add_const_to_ptr_t = std::add_pointer_t<std::add_const_t<std::remove_pointer_t<T>>>;
struct add_const_to_ptr {
using type = T;
};
template <class T>
struct add_const_to_ptr<T*> {
using type = const T*;
};
template <class T>
using add_const_to_ptr_t = typename add_const_to_ptr<T>::type;

constexpr bool test() {
test_iterator_classes<std::type_identity_t, std::type_identity_t>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,14 @@ constexpr void test_iterator_classes() {
{
std::array<int, 0> a = {};

auto ret = std::ranges::find_last_if_not(it(a.data()), sent(it(a.data())), [](auto&&) { return false; }).begin();
assert(ret == it(a.data()));
auto ret = std::ranges::find_last_if_not(it(a.begin()), sent(it(a.end())), [](auto&&) { return false; }).begin();
assert(ret == it(a.end()));
}
{
std::array<int, 0> a = {};

auto ret = std::ranges::find_last_if_not(make_range<it, sent>(a), [](auto&&) { return false; }).begin();
assert(ret == it(a.begin()));
assert(ret == it(a.end()));
}
}

Expand Down Expand Up @@ -183,8 +183,17 @@ struct NonConstComparable {
friend constexpr bool operator!=(NonConstComparable&, const NonConstComparable&) { return false; }
};

// note: this should really use `std::const_iterator`
template <class T>
using add_const_to_ptr_t = std::add_pointer_t<std::add_const_t<std::remove_pointer_t<T>>>;
struct add_const_to_ptr {
using type = T;
};
template <class T>
struct add_const_to_ptr<T*> {
using type = const T*;
};
template <class T>
using add_const_to_ptr_t = typename add_const_to_ptr<T>::type;

constexpr bool test() {
test_iterator_classes<std::type_identity_t, std::type_identity_t>();
Expand Down
118 changes: 74 additions & 44 deletions libcxx/test/support/test_iterators.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,62 +339,92 @@ cpp20_random_access_iterator(It) -> cpp20_random_access_iterator<It>;

static_assert(std::random_access_iterator<cpp20_random_access_iterator<int*>>);

template <class It>
class contiguous_iterator
{
static_assert(std::is_pointer_v<It>, "Things probably break in this case");
template <std::contiguous_iterator It>
class contiguous_iterator {
It it_;

It it_;
template <std::contiguous_iterator U>
friend class contiguous_iterator;

template <class U> friend class contiguous_iterator;
public:
typedef std::contiguous_iterator_tag iterator_category;
typedef typename std::iterator_traits<It>::value_type value_type;
typedef typename std::iterator_traits<It>::difference_type difference_type;
typedef It pointer;
typedef typename std::iterator_traits<It>::reference reference;
typedef typename std::remove_pointer<It>::type element_type;
using iterator_category = std::contiguous_iterator_tag;
using value_type = typename std::iterator_traits<It>::value_type;
using difference_type = typename std::iterator_traits<It>::difference_type;
using pointer = typename std::iterator_traits<It>::pointer;
using reference = typename std::iterator_traits<It>::reference;
using element_type = value_type;

TEST_CONSTEXPR_CXX14 It base() const {return it_;}
constexpr It base() const { return it_; }

TEST_CONSTEXPR_CXX14 contiguous_iterator() : it_() {}
TEST_CONSTEXPR_CXX14 explicit contiguous_iterator(It it) : it_(it) {}
constexpr contiguous_iterator() : it_() {}
constexpr explicit contiguous_iterator(It it) : it_(it) {}

template <class U>
TEST_CONSTEXPR_CXX14 contiguous_iterator(const contiguous_iterator<U>& u) : it_(u.it_) {}
template <class U>
constexpr contiguous_iterator(const contiguous_iterator<U>& u) : it_(u.it_) {}

template <class U, class = typename std::enable_if<std::is_default_constructible<U>::value>::type>
constexpr contiguous_iterator(contiguous_iterator<U>&& u) : it_(u.it_) { u.it_ = U(); }
template <class U, class = typename std::enable_if<std::is_default_constructible<U>::value>::type>
constexpr contiguous_iterator(contiguous_iterator<U>&& u) : it_(u.it_) {
u.it_ = U();
}

TEST_CONSTEXPR reference operator*() const {return *it_;}
TEST_CONSTEXPR pointer operator->() const {return it_;}
TEST_CONSTEXPR reference operator[](difference_type n) const {return it_[n];}

TEST_CONSTEXPR_CXX14 contiguous_iterator& operator++() {++it_; return *this;}
TEST_CONSTEXPR_CXX14 contiguous_iterator& operator--() {--it_; return *this;}
TEST_CONSTEXPR_CXX14 contiguous_iterator operator++(int) {return contiguous_iterator(it_++);}
TEST_CONSTEXPR_CXX14 contiguous_iterator operator--(int) {return contiguous_iterator(it_--);}

TEST_CONSTEXPR_CXX14 contiguous_iterator& operator+=(difference_type n) {it_ += n; return *this;}
TEST_CONSTEXPR_CXX14 contiguous_iterator& operator-=(difference_type n) {it_ -= n; return *this;}
friend TEST_CONSTEXPR_CXX14 contiguous_iterator operator+(contiguous_iterator x, difference_type n) {x += n; return x;}
friend TEST_CONSTEXPR_CXX14 contiguous_iterator operator+(difference_type n, contiguous_iterator x) {x += n; return x;}
friend TEST_CONSTEXPR_CXX14 contiguous_iterator operator-(contiguous_iterator x, difference_type n) {x -= n; return x;}
friend TEST_CONSTEXPR difference_type operator-(contiguous_iterator x, contiguous_iterator y) {return x.it_ - y.it_;}

friend TEST_CONSTEXPR bool operator==(const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ == y.it_;}
friend TEST_CONSTEXPR bool operator!=(const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ != y.it_;}
friend TEST_CONSTEXPR bool operator< (const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ < y.it_;}
friend TEST_CONSTEXPR bool operator<=(const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ <= y.it_;}
friend TEST_CONSTEXPR bool operator> (const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ > y.it_;}
friend TEST_CONSTEXPR bool operator>=(const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ >= y.it_;}
constexpr reference operator*() const { return *it_; }
constexpr pointer operator->() const { return it_; }
constexpr reference operator[](difference_type n) const { return it_[n]; }

constexpr contiguous_iterator& operator++() {
++it_;
return *this;
}
constexpr contiguous_iterator& operator--() {
--it_;
return *this;
}
constexpr contiguous_iterator operator++(int) { return contiguous_iterator(it_++); }
constexpr contiguous_iterator operator--(int) { return contiguous_iterator(it_--); }

constexpr contiguous_iterator& operator+=(difference_type n) {
it_ += n;
return *this;
}
constexpr contiguous_iterator& operator-=(difference_type n) {
it_ -= n;
return *this;
}
friend constexpr contiguous_iterator operator+(contiguous_iterator x, difference_type n) {
x += n;
return x;
}
friend constexpr contiguous_iterator operator+(difference_type n, contiguous_iterator x) {
x += n;
return x;
}
friend constexpr contiguous_iterator operator-(contiguous_iterator x, difference_type n) {
x -= n;
return x;
}
friend constexpr difference_type operator-(contiguous_iterator x, contiguous_iterator y) { return x.it_ - y.it_; }

friend constexpr bool operator==(const contiguous_iterator& x, const contiguous_iterator& y) {
return x.it_ == y.it_;
}
friend constexpr bool operator!=(const contiguous_iterator& x, const contiguous_iterator& y) {
return x.it_ != y.it_;
}
friend constexpr bool operator<(const contiguous_iterator& x, const contiguous_iterator& y) { return x.it_ < y.it_; }
friend constexpr bool operator<=(const contiguous_iterator& x, const contiguous_iterator& y) {
return x.it_ <= y.it_;
}
friend constexpr bool operator>(const contiguous_iterator& x, const contiguous_iterator& y) { return x.it_ > y.it_; }
friend constexpr bool operator>=(const contiguous_iterator& x, const contiguous_iterator& y) {
return x.it_ >= y.it_;
}

// Note no operator<=>, use three_way_contiguous_iterator for testing operator<=>

friend TEST_CONSTEXPR It base(const contiguous_iterator& i) { return i.it_; }
friend constexpr It base(const contiguous_iterator& i) { return i.it_; }

template <class T>
void operator,(T const &) = delete;
template <class T>
void operator,(T const&) = delete;
};
template <class It>
contiguous_iterator(It) -> contiguous_iterator<It>;
Expand Down
Loading