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