Skip to content

[libc++][test] Fix assumptions that std::array iterators are pointers #74430

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 7 commits into from
Dec 5, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -29,35 +29,35 @@ struct Test {
void operator()(ExecutionPolicy&& policy) {
{ // simple test
std::array a = {1, 2, 3, 4, 5, 6, 7, 8};
std::replace(policy, Iter(std::begin(a)), Iter(std::end(a)), 3, 6);
std::replace(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), 3, 6);
assert((a == std::array{1, 2, 6, 4, 5, 6, 7, 8}));
}

{ // empty range works
std::array<int, 0> a = {};
std::replace(policy, Iter(std::begin(a)), Iter(std::end(a)), 3, 6);
std::replace(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), 3, 6);
}

{ // non-empty range without a match works
std::array a = {1, 2};
std::replace(policy, Iter(std::begin(a)), Iter(std::end(a)), 3, 6);
std::replace(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), 3, 6);
}

{ // single element range works
std::array a = {3};
std::replace(policy, Iter(std::begin(a)), Iter(std::end(a)), 3, 6);
std::replace(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), 3, 6);
assert((a == std::array{6}));
}

{ // two element range works
std::array a = {3, 4};
std::replace(policy, Iter(std::begin(a)), Iter(std::end(a)), 3, 6);
std::replace(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), 3, 6);
assert((a == std::array{6, 4}));
}

{ // multiple matching elements work
std::array a = {1, 2, 3, 4, 3, 3, 5, 6, 3};
std::replace(policy, Iter(std::begin(a)), Iter(std::end(a)), 3, 9);
std::replace(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), 3, 9);
assert((a == std::array{1, 2, 9, 4, 9, 9, 5, 6, 9}));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,40 +32,40 @@ struct Test {
{ // simple test
std::array a = {1, 2, 3, 4, 5, 6, 7, 8};
std::array<int, a.size()> out;
std::replace_copy(policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(out)), 3, 6);
std::replace_copy(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), Iter(std::data(out)), 3, 6);
assert((out == std::array{1, 2, 6, 4, 5, 6, 7, 8}));
}

{ // empty range works
std::array<int, 0> a = {};
std::replace_copy(policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(a)), 3, 6);
std::replace_copy(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), Iter(std::data(a)), 3, 6);
}

{ // non-empty range without a match works
std::array a = {1, 2};
std::array<int, a.size()> out;
std::replace_copy(policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(out.data()), 3, 6);
std::replace_copy(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), Iter(out.data()), 3, 6);
assert((out == std::array{1, 2}));
}

{ // single element range works
std::array a = {3};
std::array<int, a.size()> out;
std::replace_copy(policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(out)), 3, 6);
std::replace_copy(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), Iter(std::data(out)), 3, 6);
assert((out == std::array{6}));
}

{ // two element range works
std::array a = {3, 4};
std::array<int, a.size()> out;
std::replace_copy(policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(out)), 3, 6);
std::replace_copy(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), Iter(std::data(out)), 3, 6);
assert((out == std::array{6, 4}));
}

{ // multiple matching elements work
std::array a = {1, 2, 3, 4, 3, 3, 5, 6, 3};
std::array<int, a.size()> out;
std::replace_copy(policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(out)), 3, 9);
std::replace_copy(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), Iter(std::data(out)), 3, 9);
assert((out == std::array{1, 2, 9, 4, 9, 9, 5, 6, 9}));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,45 +34,75 @@ struct Test {
std::array a = {1, 2, 3, 4, 5, 6, 7, 8};
std::array<int, a.size()> out;
std::replace_copy_if(
policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(out)), [](int i) { return i == 3; }, 6);
policy,
Iter(std::data(a)),
Iter(std::data(a) + std::size(a)),
Iter(std::data(out)),
[](int i) { return i == 3; },
6);
assert((out == std::array{1, 2, 6, 4, 5, 6, 7, 8}));
}

{ // empty range works
std::array<int, 0> a = {};
std::replace_copy_if(
policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(a)), [](int i) { return i == 3; }, 6);
policy,
Iter(std::data(a)),
Iter(std::data(a) + std::size(a)),
Iter(std::data(a)),
[](int i) { return i == 3; },
6);
}

{ // non-empty range without a match works
std::array a = {1, 2};
std::array<int, a.size()> out;
std::replace_copy_if(
policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(out.data()), [](int i) { return i == 3; }, 6);
policy,
Iter(std::data(a)),
Iter(std::data(a) + std::size(a)),
Iter(out.data()),
[](int i) { return i == 3; },
6);
assert((out == std::array{1, 2}));
}

{ // single element range works
std::array a = {3};
std::array<int, a.size()> out;
std::replace_copy_if(
policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(out)), [](int i) { return i == 3; }, 6);
policy,
Iter(std::data(a)),
Iter(std::data(a) + std::size(a)),
Iter(std::data(out)),
[](int i) { return i == 3; },
6);
assert((out == std::array{6}));
}

{ // two element range works
std::array a = {3, 4};
std::array<int, a.size()> out;
std::replace_copy_if(
policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(out)), [](int i) { return i == 3; }, 6);
policy,
Iter(std::data(a)),
Iter(std::data(a) + std::size(a)),
Iter(std::data(out)),
[](int i) { return i == 3; },
6);
assert((out == std::array{6, 4}));
}

{ // multiple matching elements work
std::array a = {1, 2, 3, 4, 3, 3, 5, 6, 3};
std::array<int, a.size()> out;
std::replace_copy_if(
policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(out)), [](int i) { return i == 3; }, 9);
policy,
Iter(std::data(a)),
Iter(std::data(a) + std::size(a)),
Iter(std::data(out)),
[](int i) { return i == 3; },
9);
assert((out == std::array{1, 2, 9, 4, 9, 9, 5, 6, 9}));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,38 +30,40 @@ struct Test {
{ // simple test
std::array a = {1, 2, 3, 4, 5, 6, 7, 8};
std::replace_if(
policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i == 3 || i == 7; }, 6);
policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), [](int i) { return i == 3 || i == 7; }, 6);
assert((a == std::array{1, 2, 6, 4, 5, 6, 6, 8}));
}

{ // empty range works
std::array<int, 0> a = {};
std::replace_if(
policy, Iter(std::begin(a)), Iter(std::end(a)), [](int) { return false; }, 6);
policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), [](int) { return false; }, 6);
}

{ // non-empty range without a match works
std::array a = {1, 2};
std::replace_if(policy, Iter(std::begin(a)), Iter(std::end(a)), [](int) { return false; }, 6);
std::replace_if(
policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), [](int) { return false; }, 6);
}

{ // single element range works
std::array a = {3};
std::replace_if(
policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i == 3; }, 6);
policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), [](int i) { return i == 3; }, 6);
assert((a == std::array{6}));
}

{ // two element range works
std::array a = {3, 4};
std::replace_if(
policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i == 3; }, 6);
policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), [](int i) { return i == 3; }, 6);
assert((a == std::array{6, 4}));
}

{ // multiple matching elements work
std::array a = {1, 2, 3, 4, 3, 3, 5, 6, 3};
std::replace_if(policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i == 3; }, 9);
std::replace_if(
policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), [](int i) { return i == 3; }, 9);
assert((a == std::array{1, 2, 9, 4, 9, 9, 5, 6, 9}));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,24 +53,36 @@ struct Test {
std::array<int, 0> a;
std::array<int, 0> b;
std::array<int, std::size(a) + std::size(b)> out;
std::merge(
policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::begin(out));
std::merge(policy,
Iter1(std::data(a)),
Iter1(std::data(a) + std::size(a)),
Iter2(std::data(b)),
Iter2(std::data(b) + std::size(b)),
std::begin(out));
}
{ // check that it works with the first range being empty
std::array<int, 0> a;
int b[] = {2, 4, 6, 8, 10};
std::array<int, std::size(a) + std::size(b)> out;
std::merge(
policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::begin(out));
std::merge(policy,
Iter1(std::data(a)),
Iter1(std::data(a) + std::size(a)),
Iter2(std::begin(b)),
Iter2(std::end(b)),
std::begin(out));
assert((out == std::array{2, 4, 6, 8, 10}));
}

{ // check that it works with the second range being empty
int a[] = {2, 4, 6, 8, 10};
std::array<int, 0> b;
std::array<int, std::size(a) + std::size(b)> out;
std::merge(
policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::begin(out));
std::merge(policy,
Iter1(std::begin(a)),
Iter1(std::end(a)),
Iter2(std::data(b)),
Iter2(std::data(b) + std::size(b)),
std::begin(out));
assert((out == std::array{2, 4, 6, 8, 10}));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@

template <typename Iter1, typename Iter2, typename C1, typename C2, typename Order>
constexpr void test_lexicographical_compare(C1 a, C2 b, Order expected) {
std::same_as<Order> decltype(auto) result =
std::lexicographical_compare_three_way(Iter1{a.begin()}, Iter1{a.end()}, Iter2{b.begin()}, Iter2{b.end()});
std::same_as<Order> decltype(auto) result = std::lexicographical_compare_three_way(
Iter1{a.data()}, Iter1{a.data() + a.size()}, Iter2{b.data()}, Iter2{b.data() + b.size()});
assert(expected == result);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ static_assert(has_lexicographical_compare<decltype(compare_int_result)>);

template <typename Iter1, typename Iter2, typename C1, typename C2, typename Order, typename Comparator>
constexpr void test_lexicographical_compare(C1 a, C2 b, Comparator comp, Order expected) {
std::same_as<Order> decltype(auto) result =
std::lexicographical_compare_three_way(Iter1{a.begin()}, Iter1{a.end()}, Iter2{b.begin()}, Iter2{b.end()}, comp);
std::same_as<Order> decltype(auto) result = std::lexicographical_compare_three_way(
Iter1{a.data()}, Iter1{a.data() + a.size()}, Iter2{b.data()}, Iter2{b.data() + b.size()}, comp);
assert(expected == result);
}

Expand Down
9 changes: 9 additions & 0 deletions libcxx/test/std/containers/from_range_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
#ifndef SUPPORT_FROM_RANGE_HELPERS_H
#define SUPPORT_FROM_RANGE_HELPERS_H

#include <array>
#include <cstddef>
#include <iterator>
#include <type_traits>
#include <vector>

#include "min_allocator.h"
#include "test_allocator.h"
Expand All @@ -34,6 +36,13 @@ constexpr auto wrap_input(Range&& input) {
return std::ranges::subrange(std::move(b), std::move(e));
}

template <class Iter, class Sent, class T, std::size_t N>
constexpr auto wrap_input(std::array<T, N>& input) {
auto b = Iter(input.data());
auto e = Sent(Iter(input.data() + input.size()));
return std::ranges::subrange(std::move(b), std::move(e));
}

template <class Iter, class Sent, class T>
constexpr auto wrap_input(std::vector<T>& input) {
auto b = Iter(input.data());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class throw_operator_minus {
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;
typedef std::remove_reference_t<reference> element_type;

throw_operator_minus() : it_() {}
explicit throw_operator_minus(It it) : it_(it) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ constexpr void test() {
using ChunkByView = std::ranges::chunk_by_view<Underlying, std::ranges::less_equal>;
using ChunkByIterator = std::ranges::iterator_t<ChunkByView>;

auto make_chunk_by_view = [](auto begin, auto end) {
View view{Iterator(begin), Sentinel(Iterator(end))};
auto make_chunk_by_view = [](auto& arr) {
View view{Iterator(arr.data()), Sentinel(Iterator(arr.data() + arr.size()))};
return ChunkByView(std::move(view), std::ranges::less_equal{});
};

// Test operator==
{
std::array array{0, 1, 2};
ChunkByView view = make_chunk_by_view(array.begin(), array.end());
ChunkByView view = make_chunk_by_view(array);
ChunkByIterator i = view.begin();
ChunkByIterator j = view.begin();

Expand All @@ -52,7 +52,7 @@ constexpr void test() {
// Test synthesized operator!=
{
std::array array{0, 1, 2};
ChunkByView view = make_chunk_by_view(array.begin(), array.end());
ChunkByView view = make_chunk_by_view(array);
ChunkByIterator i = view.begin();
ChunkByIterator j = view.begin();

Expand All @@ -65,7 +65,7 @@ constexpr void test() {
// Test operator== with std::default_sentinel_t
{
std::array array{0, 1, 2};
ChunkByView view = make_chunk_by_view(array.begin(), array.end());
ChunkByView view = make_chunk_by_view(array);
ChunkByIterator i = view.begin();

std::same_as<bool> decltype(auto) result = (i == std::default_sentinel);
Expand All @@ -77,7 +77,7 @@ constexpr void test() {
// Test synthesized operator!= with std::default_sentinel_t
{
std::array array{0, 1, 2};
ChunkByView view = make_chunk_by_view(array.begin(), array.end());
ChunkByView view = make_chunk_by_view(array);
ChunkByIterator i = view.begin();

std::same_as<bool> decltype(auto) result = (i != std::default_sentinel);
Expand Down
Loading