1 // Range v3 library
2 //
3 // Copyright Eric Niebler 2015-present
4 //
5 // Use, modification and distribution is subject to the
6 // Boost Software License, Version 1.0. (See accompanying
7 // file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
9 //
10 // Project home: https://github.com/ericniebler/range-v3
11
12 #include <list>
13 #include <vector>
14 #include <range/v3/core.hpp>
15 #include <range/v3/view/take.hpp>
16 #include <range/v3/view/take_exactly.hpp>
17 #include <range/v3/view/reverse.hpp>
18 #include <range/v3/view/counted.hpp>
19 #include <range/v3/view/delimit.hpp>
20 #include <range/v3/view/filter.hpp>
21 #include <range/v3/view/c_str.hpp>
22 #include <range/v3/utility/copy.hpp>
23 #include <range/v3/algorithm/find.hpp>
24 #include "../simple_test.hpp"
25 #include "../test_utils.hpp"
26
main()27 int main()
28 {
29 using namespace ranges;
30
31 // Reverse a random-access, common, sized range
32 std::vector<int> rgv{0,1,2,3,4,5,6,7,8,9};
33 auto const rng0 = rgv | views::reverse;
34 CPP_assert(view_<std::remove_const_t<decltype(rng0)>>);
35 CPP_assert(random_access_range<decltype(rng0)>);
36 CPP_assert(common_range<decltype(rng0)>);
37 CPP_assert(sized_range<decltype(rng0)>);
38 CHECK(rng0.size() == 10u);
39 ::check_equal(rng0, {9,8,7,6,5,4,3,2,1,0});
40 ::check_equal(rng0 | views::reverse, {0,1,2,3,4,5,6,7,8,9});
41 ::check_equal(rng0 | views::reverse | views::reverse, {9,8,7,6,5,4,3,2,1,0});
42 ::check_equal(rng0 | views::reverse | views::reverse | views::reverse, {0,1,2,3,4,5,6,7,8,9});
43
44 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
45 #if defined(__clang__) && __clang_major__ < 6
46 // Workaround https://bugs.llvm.org/show_bug.cgi?id=33314
47 RANGES_DIAGNOSTIC_PUSH
48 RANGES_DIAGNOSTIC_IGNORE_UNDEFINED_FUNC_TEMPLATE
49 #endif
50 {
51 ranges::reverse_view dg0{rgv};
52 ::check_equal(dg0, {9, 8, 7, 6, 5, 4, 3, 2, 1, 0});
53 ranges::reverse_view dg1{dg0};
54 #ifdef RANGES_WORKAROUND_MSVC_934330
55 ::check_equal(dg1, {9, 8, 7, 6, 5, 4, 3, 2, 1, 0});
56 #else // ^^^ "workaround" / no "workaround" vvv
57 ::check_equal(dg1, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9});
58 #endif // RANGES_WORKAROUND_MSVC_934330
59 }
60 #if defined(__clang__) && __clang_major__ < 6
61 RANGES_DIAGNOSTIC_POP
62 #endif // clang bug workaround
63 #endif // use deduction guides
64
65 // Reverse another random-access, non-common, sized range
66 auto cnt = counted_view<std::vector<int>::iterator>(rgv.begin(), 10);
67 CPP_assert(!common_range<decltype(cnt)>);
68 auto const rng1 = rgv | views::reverse;
69 CPP_assert(view_<std::remove_const_t<decltype(rng1)>>);
70 CPP_assert(random_access_range<decltype(rng1)>);
71 CPP_assert(common_range<decltype(rng1)>);
72 CPP_assert(sized_range<decltype(rng1)>);
73 CHECK(rng1.size() == 10u);
74 ::check_equal(rng1, {9,8,7,6,5,4,3,2,1,0});
75 ::check_equal(rng1 | views::reverse, {0,1,2,3,4,5,6,7,8,9});
76
77 // Reverse a random-access, non-common, non-sized range
78 auto sz = views::c_str((char const*)"hello");
79 auto rng2 = sz | views::reverse;
80 CPP_assert(view_<decltype(rng2)>);
81 CPP_assert(random_access_range<decltype(rng2)>);
82 CPP_assert(common_range<decltype(rng2)>);
83 CPP_assert(!sized_range<decltype(detail::as_const(rng2))>);
84 CPP_assert(sized_range<decltype(rng2)>);
85 auto const & crng2 = rng2;
86 CPP_assert(!range<decltype(crng2)>);
87 ::check_equal(rng2, {'o','l','l','e','h'});
88 ::check_equal(rng2 | views::reverse, {'h','e','l','l','o'});
89
90 // Reverse a bidirectional, common, sized range
91 std::list<int> rgl{0,1,2,3,4,5,6,7,8,9};
92 auto const rng3 = rgl | views::reverse;
93 CPP_assert(view_<std::remove_const_t<decltype(rng3)>>);
94 CPP_assert(bidirectional_range<decltype(rng3)>);
95 CPP_assert(!random_access_range<decltype(rng3)>);
96 CPP_assert(common_range<decltype(rng3)>);
97 CPP_assert(sized_range<decltype(rng3)>);
98 CHECK(rng3.size() == 10u);
99 ::check_equal(rng3, {9,8,7,6,5,4,3,2,1,0});
100 ::check_equal(rng3 | views::reverse, {0,1,2,3,4,5,6,7,8,9});
101
102 // Reverse a bidirectional, weak, sized range
103 auto cnt2 = views::counted(rgl.begin(), 10);
104 auto rng4 = cnt2 | views::reverse;
105 CPP_assert(view_<decltype(rng4)>);
106 CPP_assert(bidirectional_range<decltype(rng4)>);
107 CPP_assert(!random_access_range<decltype(rng4)>);
108 CPP_assert(common_range<decltype(rng4)>);
109 CPP_assert(sized_range<decltype(rng4)>);
110 CHECK(rng4.size() == 10u);
111 auto const & crng4 = rng4;
112 CPP_assert(!range<decltype(crng4)>);
113 ::check_equal(rng4, {9,8,7,6,5,4,3,2,1,0});
114 ::check_equal(rng4 | views::reverse, {0,1,2,3,4,5,6,7,8,9});
115
116 // Reverse a bidirectional, weak, non-sized range
117 auto dlm = views::delimit(rgl.begin(), 9);
118 CPP_assert(!common_range<decltype(dlm)>);
119 auto rng5 = dlm | views::reverse;
120 CPP_assert(view_<decltype(rng5)>);
121 CPP_assert(bidirectional_range<decltype(rng5)>);
122 CPP_assert(!random_access_range<decltype(rng5)>);
123 CPP_assert(common_range<decltype(rng5)>);
124 CPP_assert(!sized_range<decltype(rng5)>);
125 auto const & crng5 = rng5;
126 CPP_assert(!range<decltype(crng5)>);
127 ::check_equal(rng5, {8,7,6,5,4,3,2,1,0});
128 ::check_equal(rng5 | views::reverse, {0,1,2,3,4,5,6,7,8});
129
130 // Reverse a bidirectional, weak, non-sized range
131 auto dlm2 = views::delimit(rgl, 10);
132 CPP_assert(!common_range<decltype(dlm2)>);
133 auto rng6 = dlm2 | views::reverse;
134 CPP_assert(view_<decltype(rng6)>);
135 CPP_assert(bidirectional_range<decltype(rng6)>);
136 CPP_assert(!random_access_range<decltype(rng6)>);
137 CPP_assert(common_range<decltype(rng6)>);
138 CPP_assert(!sized_range<decltype(rng6)>);
139 auto const & crng6 = rng6;
140 CPP_assert(!range<decltype(crng6)>);
141 ::check_equal(rng6, {9,8,7,6,5,4,3,2,1,0});
142 ::check_equal(rng6 | views::reverse, {0,1,2,3,4,5,6,7,8,9});
143
144 {
145 std::vector<int> v = {1, 2, 3, 4, 5};
146 auto b = find(v, 2);
147 auto e = find(v | views::reverse, 4).base();
148 ::check_equal(make_subrange(b, e), {2, 3, 4});
149
150 auto e2 = find(v | views::filter([](int i){ return i%2 == 0;})
151 | views::reverse, 4);
152 CHECK(::is_dangling(e2));
153 }
154
155 return test_result();
156 }
157