brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.5 KiB · 85557ec Raw
206 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// <algorithm>10 11// UNSUPPORTED: c++03, c++11, c++14, c++1712 13// template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2>14//   requires indirectly_swappable<I1, I2>15//   constexpr ranges::swap_ranges_result<I1, I2>16//     ranges::swap_ranges(I1 first1, S1 last1, I2 first2, S2 last2);17// template<input_range R1, input_range R2>18//   requires indirectly_swappable<iterator_t<R1>, iterator_t<R2>>19//   constexpr ranges::swap_ranges_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>>20//     ranges::swap_ranges(R1&& r1, R2&& r2);21 22#include <algorithm>23#include <array>24#include <cassert>25#include <ranges>26#include <vector>27 28#include <cstdio>29 30#include "test_iterators.h"31#include "type_algorithms.h"32 33template <class Iter1, class Iter2>34TEST_CONSTEXPR_CXX20 void test_iterators() {35  using Expected = std::ranges::swap_ranges_result<Iter1, Iter2>;36  { // Basic test case: swapping three elements between two arrays37    int a[3] = {1, 2, 3};38    int b[3] = {4, 5, 6};39    std::same_as<Expected> auto r =40        std::ranges::swap_ranges(Iter1(a), sentinel_wrapper(Iter1(a + 3)), Iter2(b), sentinel_wrapper(Iter2(b + 3)));41    assert(base(r.in1) == a + 3);42    assert(base(r.in2) == b + 3);43    assert(std::ranges::equal(a, std::array{4, 5, 6}));44    assert(std::ranges::equal(b, std::array{1, 2, 3}));45  }46  { // Large-scale test: swapping 100 elements between two different containers47    const int N = 100;48    std::array<int, N> a;49    std::vector<int> b(N + 2, 42);50    b.front() = 1;51    b.back()  = -1;52    for (int i = 0; i < N; ++i)53      a[i] = i * i + 1;54    std::same_as<Expected> auto r = std::ranges::swap_ranges(55        Iter1(a.data()),56        sentinel_wrapper(Iter1(a.data() + N)),57        Iter2(b.data() + 1),58        sentinel_wrapper(Iter2(b.data() + b.size())));59    assert(base(r.in1) == a.data() + N);60    assert(base(r.in2) == b.data() + N + 1);61    assert(b.front() == 1); // Ensure that the unswapped portion remains unchanged62    assert(b.back() == -1);63    for (int i = 0; i < N; ++i) {64      assert(a[i] == 42);65      assert(b[i + 1] == i * i + 1);66    }67  }68}69 70template <std::size_t N>71constexpr void test_vector_bool() {72  { // Test swap_ranges() with aligned bytes73    std::vector<bool> f(N, false), t(N, true);74    std::ranges::swap_ranges(f, t);75    assert(std::all_of(f.begin(), f.end(), [](bool b) { return b; }));76    assert(std::all_of(t.begin(), t.end(), [](bool b) { return !b; }));77  }78  { // Test swap_ranges() with unaligned bytes79    std::vector<bool> f(N, false), t(N + 8, true);80    std::ranges::swap_ranges(f.begin(), f.end(), t.begin() + 4, t.end() - 4);81    assert(std::all_of(f.begin(), f.end(), [](bool b) { return b; }));82    assert(std::all_of(t.begin() + 4, t.end() - 4, [](bool b) { return !b; }));83  }84}85 86constexpr bool test() {87  { // Validate swapping ranges directly88    std::array r1 = {1, 2, 3};89    std::array r2 = {4, 5, 6};90 91    std::same_as<std::ranges::in_in_result<std::array<int, 3>::iterator, std::array<int, 3>::iterator>> auto r =92        std::ranges::swap_ranges(r1, r2);93    assert(r.in1 == r1.end());94    assert(r.in2 == r2.end());95    assert((r1 == std::array{4, 5, 6}));96    assert((r2 == std::array{1, 2, 3}));97  }98 99  { // Validate swapping ranges using iterator and sentinels100    int i[3]                      = {1, 2, 3};101    int j[3]                      = {4, 5, 6};102    using It                      = cpp17_input_iterator<int*>;103    using Sent                    = sentinel_wrapper<It>;104    using Expected                = std::ranges::swap_ranges_result<It, It>;105    std::same_as<Expected> auto r = std::ranges::swap_ranges(It(i), Sent(It(i + 3)), It(j), Sent(It(j + 3)));106    assert(base(r.in1) == i + 3);107    assert(base(r.in2) == j + 3);108    assert(std::ranges::equal(i, std::array{4, 5, 6}));109    assert(std::ranges::equal(j, std::array{1, 2, 3}));110  }111 112  { // Validate swapping ranges of different lengths113    using Expected                = std::ranges::swap_ranges_result<int*, int*>;114    int i[3]                      = {1, 2, 3};115    int j[1]                      = {4};116    std::same_as<Expected> auto r = std::ranges::swap_ranges(i, i + 3, j, j + 1);117    assert(r.in1 == i + 1);118    assert(r.in2 == j + 1);119    assert(std::ranges::equal(i, std::array{4, 2, 3}));120    assert(std::ranges::equal(j, std::array{1}));121    std::same_as<Expected> auto r2 = std::ranges::swap_ranges(i, j);122    assert(r2.in1 == i + 1);123    assert(r2.in2 == j + 1);124    assert(std::ranges::equal(i, std::array{1, 2, 3}));125    assert(std::ranges::equal(j, std::array{4}));126    std::same_as<Expected> auto r3 = std::ranges::swap_ranges(j, j + 1, i, i + 3);127    assert(r3.in1 == j + 1);128    assert(r3.in2 == i + 1);129    assert(std::ranges::equal(i, std::array{4, 2, 3}));130    assert(std::ranges::equal(j, std::array{1}));131    std::same_as<Expected> auto r4 = std::ranges::swap_ranges(j, i);132    assert(r4.in1 == j + 1);133    assert(r4.in2 == i + 1);134    assert(std::ranges::equal(i, std::array{1, 2, 3}));135    assert(std::ranges::equal(j, std::array{4}));136  }137 138  { // Validate swapping when one or both are borrowed input ranges (views)139    {140      int r1[] = {1, 2, 3};141      int r2[] = {4, 5, 6};142      std::ranges::swap_ranges(std::views::all(r1), r2);143      assert(std::ranges::equal(r1, std::array{4, 5, 6}));144      assert(std::ranges::equal(r2, std::array{1, 2, 3}));145    }146    {147      int r1[] = {1, 2, 3};148      int r2[] = {4, 5, 6};149      std::ranges::swap_ranges(r1, std::views::all(r2));150      assert(std::ranges::equal(r1, std::array{4, 5, 6}));151      assert(std::ranges::equal(r2, std::array{1, 2, 3}));152    }153    {154      int r1[] = {1, 2, 3};155      int r2[] = {4, 5, 6};156      std::ranges::swap_ranges(std::views::all(r1), std::views::all(r2));157      assert(std::ranges::equal(r1, std::array{4, 5, 6}));158      assert(std::ranges::equal(r2, std::array{1, 2, 3}));159    }160  }161 162  { // Validate swapping involving rvalue ranges163    {164      using Expected       = std::ranges::swap_ranges_result<std::array<int, 3>::iterator, std::ranges::dangling>;165      std::array<int, 3> r = {1, 2, 3};166      std::same_as<Expected> auto a = std::ranges::swap_ranges(r, std::array{4, 5, 6});167      assert((r == std::array{4, 5, 6}));168      assert(a.in1 == r.begin() + 3);169    }170    {171      std::array<int, 3> r = {1, 2, 3};172      using Expected       = std::ranges::swap_ranges_result<std::ranges::dangling, std::array<int, 3>::iterator>;173      std::same_as<Expected> auto b = std::ranges::swap_ranges(std::array{4, 5, 6}, r);174      assert((r == std::array{4, 5, 6}));175      assert(b.in2 == r.begin() + 3);176    }177  }178 179  types::for_each(types::cpp20_input_iterator_list<int*>(), []<class Iter1>() {180    types::for_each(types::cpp20_input_iterator_list<int*>(), []<class Iter2>() {181      test_iterators<Iter1, Iter2>();182      test_iterators<ProxyIterator<Iter1>, ProxyIterator<Iter2>>();183    });184  });185 186  { // Test vector<bool>::iterator optimization187    test_vector_bool<8>();188    test_vector_bool<19>();189    test_vector_bool<32>();190    test_vector_bool<49>();191    test_vector_bool<64>();192    test_vector_bool<199>();193    test_vector_bool<256>();194  }195  return true;196}197 198static_assert(std::same_as<std::ranges::swap_ranges_result<int, char>, std::ranges::in_in_result<int, char>>);199 200int main(int, char**) {201  test();202  static_assert(test());203 204  return 0;205}206