brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.1 KiB · 84ebedf Raw
191 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// template<ForwardIterator Iter1, ForwardIterator Iter2>12//   requires HasSwap<Iter1::reference, Iter2::reference>13//   Iter214//   swap_ranges(Iter1 first1, Iter1 last1, Iter2 first2);15 16#include <algorithm>17#include <array>18#include <cassert>19#include <memory>20#include <type_traits>21#include <utility>22#include <vector>23 24#include "test_macros.h"25#include "test_iterators.h"26#include "type_algorithms.h"27 28struct TestPtr {29  template <class Iter>30  TEST_CONSTEXPR_CXX20 void operator()() {31    types::for_each(types::forward_iterator_list<int*>(), TestImpl<Iter>());32  }33 34  template <class Iter1>35  struct TestImpl {36    template <class Iter2>37    TEST_CONSTEXPR_CXX20 void operator()() {38      { // Basic test case: swapping three elements between two arrays39        int a[] = {1, 2, 3};40        int b[] = {4, 5, 6};41        Iter2 r = std::swap_ranges(Iter1(a), Iter1(a + 3), Iter2(b));42        assert(base(r) == b + 3);43        assert(a[0] == 4 && a[1] == 5 && a[2] == 6);44        assert(b[0] == 1 && b[1] == 2 && b[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        Iter2 r = std::swap_ranges(Iter1(a.data()), Iter1(a.data() + N), Iter2(b.data() + 1));55        assert(base(r) == b.data() + N + 1);56        assert(b.front() == 1); // Ensure that the unswapped portion remains unchanged57        assert(b.back() == -1);58        for (int i = 0; i < N; ++i) {59          assert(a[i] == 42);60          assert(b[i + 1] == i * i + 1);61        }62      }63    }64  };65};66 67#if TEST_STD_VER >= 1168struct TestUniquePtr {69  template <class Iter>70  TEST_CONSTEXPR_CXX23 void operator()() {71    types::for_each(types::forward_iterator_list<std::unique_ptr<int>*>(), TestImpl<Iter>());72  }73 74  template <class Iter1>75  struct TestImpl {76    template <class Iter2>77    TEST_CONSTEXPR_CXX23 void operator()() {78      std::unique_ptr<int> a[3];79      for (int k = 0; k < 3; ++k)80        a[k].reset(new int(k + 1));81      std::unique_ptr<int> b[3];82      for (int k = 0; k < 3; ++k)83        b[k].reset(new int(k + 4));84      Iter2 r = std::swap_ranges(Iter1(a), Iter1(a + 3), Iter2(b));85      assert(base(r) == b + 3);86      assert(*a[0] == 4 && *a[1] == 5 && *a[2] == 6);87      assert(*b[0] == 1 && *b[1] == 2 && *b[2] == 3);88    }89  };90};91#endif92 93template <template <class> class Iter1, template <class> class Iter2>94TEST_CONSTEXPR_CXX20 bool test_simple_cases() {95  {96    int a[2] = {1, 2};97    int b[2] = {4, 5};98    std::swap_ranges(Iter1<int*>(a), Iter1<int*>(a + 2), Iter2<int*>(b));99    assert(a[0] == 4 && a[1] == 5);100    assert(b[0] == 1 && b[1] == 2);101  }102  {103    std::array<int, 3> a = {1, 2, 3}, a0 = a;104    std::array<int, 3> b = {4, 5, 6}, b0 = b;105    using It1 = Iter1<std::array<int, 3>::iterator>;106    using It2 = Iter2<std::array<int, 3>::iterator>;107    std::swap_ranges(It1(a.begin()), It1(a.end()), It2(b.begin()));108    assert(a == b0);109    assert(b == a0);110  }111  {112    std::array<std::array<int, 2>, 2> a = {{{0, 1}, {2, 3}}}, a0 = a;113    std::array<std::array<int, 2>, 2> b = {{{9, 8}, {7, 6}}}, b0 = b;114    using It1 = Iter1<std::array<std::array<int, 2>, 2>::iterator>;115    using It2 = Iter2<std::array<std::array<int, 2>, 2>::iterator>;116    std::swap_ranges(It1(a.begin()), It1(a.end()), It2(b.begin()));117    assert(a == b0);118    assert(b == a0);119  }120  {121    std::array<std::array<int, 3>, 3> a = {{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}}, a0 = a;122    std::array<std::array<int, 3>, 3> b = {{{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}, b0 = b;123    using It1 = Iter1<std::array<std::array<int, 3>, 3>::iterator>;124    using It2 = Iter2<std::array<std::array<int, 3>, 3>::iterator>;125    std::swap_ranges(It1(a.begin()), It1(a.end()), It2(b.begin()));126    assert(a == b0);127    assert(b == a0);128  }129 130  return true;131}132 133template <std::size_t N>134TEST_CONSTEXPR_CXX20 void test_vector_bool() {135  std::vector<bool> f(N, false), t(N, true);136  { // Test swap_ranges() with aligned bytes137    std::vector<bool> f1 = f, t1 = t;138    std::swap_ranges(f1.begin(), f1.end(), t1.begin());139    assert(f1 == t);140    assert(t1 == f);141  }142  { // Test swap_ranges() with unaligned bytes143    std::vector<bool> f1(N, false), t1(N + 8, true);144    std::swap_ranges(f1.begin(), f1.end(), t1.begin() + 4);145    assert(std::equal(f1.begin(), f1.end(), t.begin()));146    assert(std::equal(t1.begin() + 4, t1.end() - 4, f.begin()));147  }148}149 150TEST_CONSTEXPR_CXX20 bool test() {151  test_simple_cases<forward_iterator, forward_iterator>();152  test_simple_cases<forward_iterator, bidirectional_iterator>();153  test_simple_cases<forward_iterator, random_access_iterator>();154  test_simple_cases<bidirectional_iterator, forward_iterator>();155  test_simple_cases<bidirectional_iterator, bidirectional_iterator>();156  test_simple_cases<bidirectional_iterator, random_access_iterator>();157  test_simple_cases<random_access_iterator, random_access_iterator>();158#if TEST_STD_VER >= 20159  test_simple_cases<std::type_identity_t, std::type_identity_t>();160#endif161 162  types::for_each(types::forward_iterator_list<int*>(), TestPtr());163 164#if TEST_STD_VER >= 11165  // We can't test unique_ptr in constant evaluation before C++23 as it's constexpr only since C++23.166  if (TEST_STD_AT_LEAST_23_OR_RUNTIME_EVALUATED)167    types::for_each(types::forward_iterator_list<std::unique_ptr<int>*>(), TestUniquePtr());168#endif169 170  { // Test vector<bool>::iterator optimization171    test_vector_bool<8>();172    test_vector_bool<19>();173    test_vector_bool<32>();174    test_vector_bool<49>();175    test_vector_bool<64>();176    test_vector_bool<199>();177    test_vector_bool<256>();178  }179 180  return true;181}182 183int main(int, char**) {184  test();185#if TEST_STD_VER >= 20186  static_assert(test());187#endif188 189  return 0;190}191