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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14, c++17 10 // TODO: make `join_view` non-experimental once D2770 is implemented. 11 // UNSUPPORTED: !c++experimental 12 13 #include <algorithm> 14 #include <array> 15 #include <cassert> 16 #include <concepts> 17 #include <deque> 18 #include <ranges> 19 #include <vector> 20 21 #include "test_iterators.h" 22 #include "type_algorithms.h" 23 24 template <class InContainer, class OutContainer> 25 constexpr void test_containers() { 26 using InIter = typename InContainer::iterator; 27 using OutIter = typename OutContainer::iterator; 28 29 { 30 InContainer in{1, 2, 3, 4}; 31 OutContainer out(4); 32 33 std::same_as<std::ranges::in_out_result<InIter, OutIter>> auto ret = 34 std::ranges::copy_n(in.begin(), in.size(), out.begin()); 35 assert(std::ranges::equal(in, out)); 36 assert(ret.in == in.end()); 37 assert(ret.out == out.end()); 38 } 39 } 40 41 template <class Iter, class Sent> 42 constexpr void test_join_view() { 43 auto to_subranges = std::views::transform([](auto& vec) { 44 return std::ranges::subrange(Iter(vec.data()), Sent(Iter(vec.data() + vec.size()))); 45 }); 46 47 { // segmented -> contiguous 48 std::vector<std::vector<int>> vectors = {}; 49 auto range = vectors | to_subranges; 50 std::vector<std::ranges::subrange<Iter, Sent>> subrange_vector(range.begin(), range.end()); 51 std::array<int, 0> arr; 52 53 std::ranges::copy_n((subrange_vector | std::views::join).begin(), 54 std::ranges::distance(subrange_vector | std::views::join), 55 arr.begin()); 56 assert(std::ranges::equal(arr, std::array<int, 0>{})); 57 } 58 { // segmented -> contiguous 59 std::vector<std::vector<int>> vectors = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10}, {}}; 60 auto range = vectors | to_subranges; 61 std::vector<std::ranges::subrange<Iter, Sent>> subrange_vector(range.begin(), range.end()); 62 std::array<int, 10> arr; 63 64 std::ranges::copy_n((subrange_vector | std::views::join).begin(), 65 std::ranges::distance(subrange_vector | std::views::join), 66 arr.begin()); 67 assert(std::ranges::equal(arr, std::array{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})); 68 } 69 { // contiguous -> segmented 70 std::vector<std::vector<int>> vectors = {{0, 0, 0, 0}, {0, 0}, {0, 0, 0, 0}, {}}; 71 auto range = vectors | to_subranges; 72 std::vector<std::ranges::subrange<Iter, Sent>> subrange_vector(range.begin(), range.end()); 73 std::array arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 74 75 std::ranges::copy_n(arr.begin(), arr.size(), (subrange_vector | std::views::join).begin()); 76 assert(std::ranges::equal(subrange_vector | std::views::join, std::array{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})); 77 } 78 { // segmented -> segmented 79 std::vector<std::vector<int>> vectors = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10}, {}}; 80 auto range1 = vectors | to_subranges; 81 std::vector<std::ranges::subrange<Iter, Sent>> subrange_vector(range1.begin(), range1.end()); 82 std::vector<std::vector<int>> to_vectors = {{0, 0, 0, 0}, {0, 0, 0, 0}, {}, {0, 0}}; 83 auto range2 = to_vectors | to_subranges; 84 std::vector<std::ranges::subrange<Iter, Sent>> to_subrange_vector(range2.begin(), range2.end()); 85 86 std::ranges::copy_n((subrange_vector | std::views::join).begin(), 87 std::ranges::distance(subrange_vector | std::views::join), 88 (to_subrange_vector | std::views::join).begin()); 89 assert(std::ranges::equal(to_subrange_vector | std::views::join, std::array{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})); 90 } 91 } 92 93 constexpr bool test_constexpr() { 94 test_containers<std::vector<int>, std::vector<int>>(); 95 96 // TODO: this should be cpp20_input_iterator_list, not forward_iterator_list 97 types::for_each(types::forward_iterator_list<int*>{}, []<class Iter> { 98 test_join_view<Iter, Iter>(); 99 test_join_view<Iter, sentinel_wrapper<Iter>>(); 100 test_join_view<Iter, sized_sentinel<Iter>>(); 101 }); 102 return true; 103 } 104 105 int main(int, char**) { 106 test_containers<std::deque<int>, std::deque<int>>(); 107 test_containers<std::deque<int>, std::vector<int>>(); 108 test_containers<std::vector<int>, std::deque<int>>(); 109 110 test_constexpr(); 111 static_assert(test_constexpr()); 112 113 return 0; 114 } 115