Skip to content

[libc++][test] Refactor tests for ranges::swap_range algorithms #121138

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 9 commits into from
Feb 26, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -10,35 +10,43 @@

// template<Iterator Iter1, Iterator Iter2>
// requires HasSwap<Iter1::reference, Iter2::reference>
// void
// iter_swap(Iter1 a, Iter2 b);
// void iter_swap(Iter1 a, Iter2 b); // constexpr since C++20

#include <algorithm>
#include <cassert>

#include "test_macros.h"

#if TEST_STD_VER > 17
constexpr bool test_swap_constexpr()
{
int i = 1;
int j = 2;
std::iter_swap(&i, &j);
return i == 2 && j == 1;
#include "test_iterators.h"
#include "type_algorithms.h"

struct TestIterators {
template <class Iter>
TEST_CONSTEXPR_CXX20 void operator()() {
types::for_each(types::forward_iterator_list<int*>(), TestImpl<Iter>());
}

template <class Iter1>
struct TestImpl {
template <class Iter2>
TEST_CONSTEXPR_CXX20 void operator()() {
int i = 1;
int j = 2;
std::iter_swap(Iter1(&i), Iter2(&j));
assert(i == 2 && j == 1);
}
};
};

TEST_CONSTEXPR_CXX20 bool test() {
types::for_each(types::forward_iterator_list<int*>(), TestIterators());
return true;
}
#endif // TEST_STD_VER > 17

int main(int, char**)
{
int i = 1;
int j = 2;
std::iter_swap(&i, &j);
assert(i == 2);
assert(j == 1);

#if TEST_STD_VER > 17
static_assert(test_swap_constexpr());
#endif // TEST_STD_VER > 17

int main(int, char**) {
test();
#if TEST_STD_VER >= 20
static_assert(test());
#endif

return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,51 +24,45 @@
#include <cassert>
#include <ranges>

#include <cstdio>

#include "test_iterators.h"
#include "type_algorithms.h"

constexpr void test_different_lengths() {
using Expected = std::ranges::swap_ranges_result<int*, int*>;
int i[3] = {1, 2, 3};
int j[1] = {4};
using Expected = std::ranges::swap_ranges_result<int*, int*>;
int i[3] = {1, 2, 3};
int j[1] = {4};
std::same_as<Expected> auto r = std::ranges::swap_ranges(i, i + 3, j, j + 1);
assert(r.in1 == i + 1);
assert(r.in2 == j + 1);
assert(i[0] == 4);
assert(i[1] == 2);
assert(i[2] == 3);
assert(j[0] == 1);
assert(std::ranges::equal(i, std::array{4, 2, 3}));
assert(std::ranges::equal(j, std::array{1}));
std::same_as<Expected> auto r2 = std::ranges::swap_ranges(i, j);
assert(r2.in1 == i + 1);
assert(r2.in2 == j + 1);
assert(i[0] == 1);
assert(i[1] == 2);
assert(i[2] == 3);
assert(j[0] == 4);
assert(std::ranges::equal(i, std::array{1, 2, 3}));
assert(std::ranges::equal(j, std::array{4}));
std::same_as<Expected> auto r3 = std::ranges::swap_ranges(j, j + 1, i, i + 3);
assert(r3.in1 == j + 1);
assert(r3.in2 == i + 1);
assert(i[0] == 4);
assert(i[1] == 2);
assert(i[2] == 3);
assert(j[0] == 1);
assert(std::ranges::equal(i, std::array{4, 2, 3}));
assert(std::ranges::equal(j, std::array{1}));
std::same_as<Expected> auto r4 = std::ranges::swap_ranges(j, i);
assert(r4.in1 == j + 1);
assert(r4.in2 == i + 1);
assert(i[0] == 1);
assert(i[1] == 2);
assert(i[2] == 3);
assert(j[0] == 4);
assert(std::ranges::equal(i, std::array{1, 2, 3}));
assert(std::ranges::equal(j, std::array{4}));
}

constexpr void test_range() {
std::array r1 = {1, 2, 3};
std::array r2 = {4, 5, 6};


std::same_as<std::ranges::in_in_result<std::array<int, 3>::iterator, std::array<int, 3>::iterator>> auto r = std::ranges::swap_ranges(r1, r2);
std::same_as<std::ranges::in_in_result<std::array<int, 3>::iterator, std::array<int, 3>::iterator>> auto r =
std::ranges::swap_ranges(r1, r2);
assert(r.in1 == r1.end());
assert(r.in2 == r2.end());

assert((r1 == std::array{4, 5, 6}));
assert((r2 == std::array{1, 2, 3}));
}
Expand All @@ -78,142 +72,82 @@ constexpr void test_borrowed_input_range() {
int r1[] = {1, 2, 3};
int r2[] = {4, 5, 6};
std::ranges::swap_ranges(std::views::all(r1), r2);
assert(r1[0] == 4);
assert(r1[1] == 5);
assert(r1[2] == 6);
assert(r2[0] == 1);
assert(r2[1] == 2);
assert(r2[2] == 3);
assert(std::ranges::equal(r1, std::array{4, 5, 6}));
assert(std::ranges::equal(r2, std::array{1, 2, 3}));
}
{
int r1[] = {1, 2, 3};
int r2[] = {4, 5, 6};
std::ranges::swap_ranges(r1, std::views::all(r2));
assert(r1[0] == 4);
assert(r1[1] == 5);
assert(r1[2] == 6);
assert(r2[0] == 1);
assert(r2[1] == 2);
assert(r2[2] == 3);
assert(std::ranges::equal(r1, std::array{4, 5, 6}));
assert(std::ranges::equal(r2, std::array{1, 2, 3}));
}
{
int r1[] = {1, 2, 3};
int r2[] = {4, 5, 6};
std::ranges::swap_ranges(std::views::all(r1), std::views::all(r2));
assert(r1[0] == 4);
assert(r1[1] == 5);
assert(r1[2] == 6);
assert(r2[0] == 1);
assert(r2[1] == 2);
assert(r2[2] == 3);
assert(std::ranges::equal(r1, std::array{4, 5, 6}));
assert(std::ranges::equal(r2, std::array{1, 2, 3}));
}
}

constexpr void test_sentinel() {
int i[3] = {1, 2, 3};
int j[3] = {4, 5, 6};
using It = cpp17_input_iterator<int*>;
using Sent = sentinel_wrapper<It>;
using Expected = std::ranges::swap_ranges_result<It, It>;
std::same_as<Expected> auto r =
std::ranges::swap_ranges(It(i), Sent(It(i + 3)), It(j), Sent(It(j + 3)));
int i[3] = {1, 2, 3};
int j[3] = {4, 5, 6};
using It = cpp17_input_iterator<int*>;
using Sent = sentinel_wrapper<It>;
using Expected = std::ranges::swap_ranges_result<It, It>;
std::same_as<Expected> auto r = std::ranges::swap_ranges(It(i), Sent(It(i + 3)), It(j), Sent(It(j + 3)));
assert(base(r.in1) == i + 3);
assert(base(r.in2) == j + 3);
assert(i[0] == 4);
assert(i[1] == 5);
assert(i[2] == 6);
assert(j[0] == 1);
assert(j[1] == 2);
assert(j[2] == 3);
assert(std::ranges::equal(i, std::array{4, 5, 6}));
assert(std::ranges::equal(j, std::array{1, 2, 3}));
}

template <class Iter1, class Iter2>
constexpr void test_iterators() {
TEST_CONSTEXPR_CXX20 void test_iterators() {
using Expected = std::ranges::swap_ranges_result<Iter1, Iter2>;
int i[3] = {1, 2, 3};
int j[3] = {4, 5, 6};
int a[3] = {1, 2, 3};
int b[3] = {4, 5, 6};
std::same_as<Expected> auto r =
std::ranges::swap_ranges(Iter1(i), sentinel_wrapper(Iter1(i + 3)), Iter2(j), sentinel_wrapper(Iter2(j + 3)));
assert(base(r.in1) == i + 3);
assert(base(r.in2) == j + 3);
assert(i[0] == 4);
assert(i[1] == 5);
assert(i[2] == 6);
assert(j[0] == 1);
assert(j[1] == 2);
assert(j[2] == 3);
std::ranges::swap_ranges(Iter1(a), sentinel_wrapper(Iter1(a + 3)), Iter2(b), sentinel_wrapper(Iter2(b + 3)));
assert(base(r.in1) == a + 3);
assert(base(r.in2) == b + 3);
assert(std::ranges::equal(a, std::array{4, 5, 6}));
assert(std::ranges::equal(b, std::array{1, 2, 3}));
}

constexpr void test_rval_range() {
{
using Expected = std::ranges::swap_ranges_result<std::array<int, 3>::iterator, std::ranges::dangling>;
using Expected = std::ranges::swap_ranges_result<std::array<int, 3>::iterator, std::ranges::dangling>;
std::array<int, 3> r = {1, 2, 3};
std::same_as<Expected> auto a = std::ranges::swap_ranges(r, std::array{4, 5, 6});
assert((r == std::array{4, 5, 6}));
assert(a.in1 == r.begin() + 3);
}
{
std::array<int, 3> r = {1, 2, 3};
using Expected = std::ranges::swap_ranges_result<std::ranges::dangling, std::array<int, 3>::iterator>;
using Expected = std::ranges::swap_ranges_result<std::ranges::dangling, std::array<int, 3>::iterator>;
std::same_as<Expected> auto b = std::ranges::swap_ranges(std::array{4, 5, 6}, r);
assert((r == std::array{4, 5, 6}));
assert(b.in2 == r.begin() + 3);
}
}

template <class Out>
constexpr void test_proxy_in_iterators() {
test_iterators<ProxyIterator<cpp20_input_iterator<int*>>, Out>();
test_iterators<ProxyIterator<forward_iterator<int*>>, Out>();
test_iterators<ProxyIterator<bidirectional_iterator<int*>>, Out>();
test_iterators<ProxyIterator<random_access_iterator<int*>>, Out>();
test_iterators<ProxyIterator<contiguous_iterator<int*>>, Out>();
}

constexpr bool test() {
test_range();

test_iterators<cpp20_input_iterator<int*>, cpp20_input_iterator<int*>>();
test_iterators<cpp20_input_iterator<int*>, forward_iterator<int*>>();
test_iterators<cpp20_input_iterator<int*>, bidirectional_iterator<int*>>();
test_iterators<cpp20_input_iterator<int*>, random_access_iterator<int*>>();
test_iterators<cpp20_input_iterator<int*>, int*>();

test_iterators<forward_iterator<int*>, cpp20_input_iterator<int*>>();
test_iterators<forward_iterator<int*>, forward_iterator<int*>>();
test_iterators<forward_iterator<int*>, bidirectional_iterator<int*>>();
test_iterators<forward_iterator<int*>, random_access_iterator<int*>>();
test_iterators<forward_iterator<int*>, int*>();

test_iterators<bidirectional_iterator<int*>, cpp20_input_iterator<int*>>();
test_iterators<bidirectional_iterator<int*>, forward_iterator<int*>>();
test_iterators<bidirectional_iterator<int*>, bidirectional_iterator<int*>>();
test_iterators<bidirectional_iterator<int*>, random_access_iterator<int*>>();
test_iterators<bidirectional_iterator<int*>, int*>();

test_iterators<random_access_iterator<int*>, cpp20_input_iterator<int*>>();
test_iterators<random_access_iterator<int*>, forward_iterator<int*>>();
test_iterators<random_access_iterator<int*>, bidirectional_iterator<int*>>();
test_iterators<random_access_iterator<int*>, random_access_iterator<int*>>();
test_iterators<random_access_iterator<int*>, int*>();

test_iterators<int*, cpp20_input_iterator<int*>>();
test_iterators<int*, forward_iterator<int*>>();
test_iterators<int*, bidirectional_iterator<int*>>();
test_iterators<int*, random_access_iterator<int*>>();
test_iterators<int*, int*>();

test_proxy_in_iterators<ProxyIterator<cpp20_input_iterator<int*>>>();
test_proxy_in_iterators<ProxyIterator<forward_iterator<int*>>>();
test_proxy_in_iterators<ProxyIterator<bidirectional_iterator<int*>>>();
test_proxy_in_iterators<ProxyIterator<random_access_iterator<int*>>>();
test_proxy_in_iterators<ProxyIterator<contiguous_iterator<int*>>>();

test_sentinel();
test_different_lengths();
test_borrowed_input_range();
test_rval_range();

types::for_each(types::cpp20_input_iterator_list<int*>(), []<class Iter1>() {
types::for_each(types::cpp20_input_iterator_list<int*>(), []<class Iter2>() {
test_iterators<Iter1, Iter2>();
test_iterators<ProxyIterator<Iter1>, ProxyIterator<Iter2>>();
});
});

return true;
}

Expand Down
Loading
Loading