xref: /llvm-project/libcxx/test/std/algorithms/alg.nonmodifying/alg.ends_with/ranges.ends_with.pass.cpp (revision f73050e722dd2e484358d03674eb186f3a2f4799)
10218ea4aSZijun Zhao //===----------------------------------------------------------------------===//
20218ea4aSZijun Zhao //
30218ea4aSZijun Zhao // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40218ea4aSZijun Zhao // See https://llvm.org/LICENSE.txt for license information.
50218ea4aSZijun Zhao // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60218ea4aSZijun Zhao //
70218ea4aSZijun Zhao //===----------------------------------------------------------------------===//
80218ea4aSZijun Zhao 
90218ea4aSZijun Zhao // <algorithm>
100218ea4aSZijun Zhao 
110218ea4aSZijun Zhao // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
120218ea4aSZijun Zhao 
130218ea4aSZijun Zhao // template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2,
140218ea4aSZijun Zhao //          class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity>
150218ea4aSZijun Zhao //   requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2>
160218ea4aSZijun Zhao //   constexpr bool ranges::ends_with(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {},
170218ea4aSZijun Zhao //                                      Proj1 proj1 = {}, Proj2 proj2 = {});
180218ea4aSZijun Zhao // template<input_range R1, input_range R2, class Pred = ranges::equal_to, class Proj1 = identity,
190218ea4aSZijun Zhao //          class Proj2 = identity>
200218ea4aSZijun Zhao //   requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2>
210218ea4aSZijun Zhao //   constexpr bool ranges::ends_with(R1&& r1, R2&& r2, Pred pred = {},
220218ea4aSZijun Zhao //                                      Proj1 proj1 = {}, Proj2 proj2 = {});
230218ea4aSZijun Zhao 
240218ea4aSZijun Zhao #include <algorithm>
250218ea4aSZijun Zhao #include <array>
260218ea4aSZijun Zhao #include <chrono>
270218ea4aSZijun Zhao #include <ranges>
280218ea4aSZijun Zhao #include "almost_satisfies_types.h"
290218ea4aSZijun Zhao #include "test_iterators.h"
300218ea4aSZijun Zhao 
310218ea4aSZijun Zhao using namespace std::chrono;
320218ea4aSZijun Zhao 
330218ea4aSZijun Zhao template <class Iter1, class Sent1 = Iter1, class Iter2 = int*, class Sent2 = Iter2>
340218ea4aSZijun Zhao concept HasEndsWithIt = requires(Iter1 first1, Sent1 last1, Iter2 first2, Sent2 last2) {
350218ea4aSZijun Zhao   std::ranges::ends_with(first1, last1, first2, last2);
360218ea4aSZijun Zhao };
370218ea4aSZijun Zhao 
380218ea4aSZijun Zhao static_assert(HasEndsWithIt<int*>);
390218ea4aSZijun Zhao static_assert(!HasEndsWithIt<ForwardIteratorNotDerivedFrom>);
400218ea4aSZijun Zhao static_assert(!HasEndsWithIt<ForwardIteratorNotIncrementable>);
410218ea4aSZijun Zhao static_assert(HasEndsWithIt<int*, int*>);
420218ea4aSZijun Zhao static_assert(!HasEndsWithIt<int*, SentinelForNotSemiregular>);
430218ea4aSZijun Zhao static_assert(!HasEndsWithIt<int*, int*, int**>); // not indirectly comparable
440218ea4aSZijun Zhao static_assert(!HasEndsWithIt<int*, SentinelForNotWeaklyEqualityComparableWith>);
450218ea4aSZijun Zhao static_assert(!HasEndsWithIt<int*, int*, ForwardIteratorNotDerivedFrom>);
460218ea4aSZijun Zhao static_assert(!HasEndsWithIt<int*, int*, ForwardIteratorNotIncrementable>);
470218ea4aSZijun Zhao static_assert(!HasEndsWithIt<int*, int*, int*, SentinelForNotSemiregular>);
480218ea4aSZijun Zhao static_assert(!HasEndsWithIt<int*, int*, int*, SentinelForNotWeaklyEqualityComparableWith>);
490218ea4aSZijun Zhao 
500218ea4aSZijun Zhao template <class Range1, class Range2 = UncheckedRange<int*>>
510218ea4aSZijun Zhao concept HasEndsWithR = requires(Range1&& range1, Range2&& range2) {
52*f73050e7SLouis Dionne   std::ranges::ends_with(std::forward<Range1>(range1), std::forward<Range2>(range2));
53*f73050e7SLouis Dionne };
540218ea4aSZijun Zhao 
550218ea4aSZijun Zhao static_assert(HasEndsWithR<UncheckedRange<int*>>);
560218ea4aSZijun Zhao static_assert(!HasEndsWithR<ForwardRangeNotDerivedFrom>);
570218ea4aSZijun Zhao static_assert(!HasEndsWithR<ForwardIteratorNotIncrementable>);
580218ea4aSZijun Zhao static_assert(!HasEndsWithR<ForwardRangeNotSentinelSemiregular>);
590218ea4aSZijun Zhao static_assert(!HasEndsWithR<ForwardRangeNotSentinelEqualityComparableWith>);
600218ea4aSZijun Zhao static_assert(HasEndsWithR<UncheckedRange<int*>, UncheckedRange<int*>>);
610218ea4aSZijun Zhao static_assert(!HasEndsWithR<UncheckedRange<int*>, UncheckedRange<int**>>); // not indirectly comparable
620218ea4aSZijun Zhao static_assert(!HasEndsWithR<UncheckedRange<int*>, ForwardRangeNotDerivedFrom>);
630218ea4aSZijun Zhao static_assert(!HasEndsWithR<UncheckedRange<int*>, ForwardRangeNotSentinelSemiregular>);
640218ea4aSZijun Zhao 
650218ea4aSZijun Zhao template <class Iter1, class Sent1 = Iter1, class Iter2, class Sent2 = Iter2>
660218ea4aSZijun Zhao constexpr void test_iterators() {
670218ea4aSZijun Zhao   { // simple tests
680218ea4aSZijun Zhao     int a[] = {1, 2, 3, 4, 5, 6};
690218ea4aSZijun Zhao     int p[] = {4, 5, 6};
70*f73050e7SLouis Dionne     {
710218ea4aSZijun Zhao       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
720218ea4aSZijun Zhao       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
73*f73050e7SLouis Dionne       [[maybe_unused]] std::same_as<bool> decltype(auto) ret =
74*f73050e7SLouis Dionne           std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
750218ea4aSZijun Zhao       assert(ret);
760218ea4aSZijun Zhao     }
770218ea4aSZijun Zhao     {
78*f73050e7SLouis Dionne       auto whole                                             = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
79*f73050e7SLouis Dionne       auto suffix                                            = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
800218ea4aSZijun Zhao       [[maybe_unused]] std::same_as<bool> decltype(auto) ret = std::ranges::ends_with(whole, suffix);
810218ea4aSZijun Zhao       assert(ret);
820218ea4aSZijun Zhao     }
830218ea4aSZijun Zhao   }
840218ea4aSZijun Zhao 
850218ea4aSZijun Zhao   { // suffix doesn't match
860218ea4aSZijun Zhao     int a[] = {1, 2, 3, 4, 5, 6};
870218ea4aSZijun Zhao     int p[] = {1, 2, 3};
88*f73050e7SLouis Dionne     {
890218ea4aSZijun Zhao       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
900218ea4aSZijun Zhao       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
910218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
920218ea4aSZijun Zhao       assert(!ret);
930218ea4aSZijun Zhao     }
940218ea4aSZijun Zhao     {
95*f73050e7SLouis Dionne       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
96*f73050e7SLouis Dionne       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
970218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole, suffix);
980218ea4aSZijun Zhao       assert(!ret);
990218ea4aSZijun Zhao     }
1000218ea4aSZijun Zhao   }
1010218ea4aSZijun Zhao 
1020218ea4aSZijun Zhao   { // range consists of just one element
1030218ea4aSZijun Zhao     int a[] = {1};
1040218ea4aSZijun Zhao     int p[] = {1};
105*f73050e7SLouis Dionne     {
1060218ea4aSZijun Zhao       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 1)));
1070218ea4aSZijun Zhao       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 1)));
1080218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
1090218ea4aSZijun Zhao       assert(ret);
1100218ea4aSZijun Zhao     }
1110218ea4aSZijun Zhao     {
112*f73050e7SLouis Dionne       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 1)));
113*f73050e7SLouis Dionne       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 1)));
1140218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole, suffix);
1150218ea4aSZijun Zhao       assert(ret);
1160218ea4aSZijun Zhao     }
1170218ea4aSZijun Zhao   }
1180218ea4aSZijun Zhao 
1190218ea4aSZijun Zhao   { // suffix consists of just one element
1200218ea4aSZijun Zhao     int a[] = {5, 1, 2, 4, 3};
1210218ea4aSZijun Zhao     int p[] = {3};
122*f73050e7SLouis Dionne     {
1230218ea4aSZijun Zhao       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 5)));
1240218ea4aSZijun Zhao       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 1)));
1250218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
1260218ea4aSZijun Zhao       assert(ret);
1270218ea4aSZijun Zhao     }
1280218ea4aSZijun Zhao     {
129*f73050e7SLouis Dionne       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 5)));
130*f73050e7SLouis Dionne       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 1)));
1310218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole, suffix);
1320218ea4aSZijun Zhao       assert(ret);
1330218ea4aSZijun Zhao     }
1340218ea4aSZijun Zhao   }
1350218ea4aSZijun Zhao 
1360218ea4aSZijun Zhao   { // range and suffix are identical
1370218ea4aSZijun Zhao     int a[] = {1, 2, 3, 4, 5, 6};
1380218ea4aSZijun Zhao     int p[] = {1, 2, 3, 4, 5, 6};
139*f73050e7SLouis Dionne     {
1400218ea4aSZijun Zhao       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
1410218ea4aSZijun Zhao       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 6)));
1420218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
1430218ea4aSZijun Zhao       assert(ret);
1440218ea4aSZijun Zhao     }
1450218ea4aSZijun Zhao     {
146*f73050e7SLouis Dionne       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
147*f73050e7SLouis Dionne       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 6)));
1480218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole, suffix);
1490218ea4aSZijun Zhao       assert(ret);
1500218ea4aSZijun Zhao     }
1510218ea4aSZijun Zhao   }
1520218ea4aSZijun Zhao 
1530218ea4aSZijun Zhao   { // suffix is longer than range
1540218ea4aSZijun Zhao     int a[] = {3, 4, 5, 6, 7, 8};
1550218ea4aSZijun Zhao     int p[] = {1, 2, 3, 4, 5, 6, 7, 8};
156*f73050e7SLouis Dionne     {
1570218ea4aSZijun Zhao       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
1580218ea4aSZijun Zhao       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 8)));
1590218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
1600218ea4aSZijun Zhao       assert(!ret);
1610218ea4aSZijun Zhao     }
1620218ea4aSZijun Zhao     {
163*f73050e7SLouis Dionne       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
164*f73050e7SLouis Dionne       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 8)));
1650218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole, suffix);
1660218ea4aSZijun Zhao       assert(!ret);
1670218ea4aSZijun Zhao     }
1680218ea4aSZijun Zhao   }
1690218ea4aSZijun Zhao 
1700218ea4aSZijun Zhao   { // suffix has zero length
1710218ea4aSZijun Zhao     int a[]              = {1, 2, 3, 4, 5, 6};
172c000f754SStephan T. Lavavej     std::array<int, 0> p = {};
173*f73050e7SLouis Dionne     {
1740218ea4aSZijun Zhao       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
175c000f754SStephan T. Lavavej       auto suffix = std::ranges::subrange(Iter2(p.data()), Sent2(Iter2(p.data())));
1760218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
1770218ea4aSZijun Zhao       assert(ret);
1780218ea4aSZijun Zhao     }
1790218ea4aSZijun Zhao     {
180*f73050e7SLouis Dionne       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
181*f73050e7SLouis Dionne       auto suffix = std::ranges::subrange(Iter2(p.data()), Sent2(Iter2(p.data())));
1820218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole, suffix);
1830218ea4aSZijun Zhao       assert(ret);
1840218ea4aSZijun Zhao     }
1850218ea4aSZijun Zhao   }
1860218ea4aSZijun Zhao 
1870218ea4aSZijun Zhao   { // range has zero length
188c000f754SStephan T. Lavavej     std::array<int, 0> a = {};
1890218ea4aSZijun Zhao     int p[]              = {1, 2, 3, 4, 5, 6, 7, 8};
190*f73050e7SLouis Dionne     {
191c000f754SStephan T. Lavavej       auto whole  = std::ranges::subrange(Iter1(a.data()), Sent1(Iter1(a.data())));
1920218ea4aSZijun Zhao       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 8)));
1930218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
1940218ea4aSZijun Zhao       assert(!ret);
1950218ea4aSZijun Zhao     }
1960218ea4aSZijun Zhao     {
197*f73050e7SLouis Dionne       auto whole  = std::ranges::subrange(Iter1(a.data()), Sent1(Iter1(a.data())));
198*f73050e7SLouis Dionne       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 8)));
1990218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole, suffix);
2000218ea4aSZijun Zhao       assert(!ret);
2010218ea4aSZijun Zhao     }
2020218ea4aSZijun Zhao   }
2030218ea4aSZijun Zhao 
2040218ea4aSZijun Zhao   { // subarray
2050218ea4aSZijun Zhao     int a[] = {0, 3, 5, 10, 7, 3, 5, 89, 3, 5, 2, 1, 8, 6};
2060218ea4aSZijun Zhao     int p[] = {3, 5};
207*f73050e7SLouis Dionne     {
2080218ea4aSZijun Zhao       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 13)));
2090218ea4aSZijun Zhao       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 2)));
2100218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
2110218ea4aSZijun Zhao       assert(!ret);
2120218ea4aSZijun Zhao     }
2130218ea4aSZijun Zhao     {
214*f73050e7SLouis Dionne       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 13)));
215*f73050e7SLouis Dionne       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 2)));
2160218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole, suffix);
2170218ea4aSZijun Zhao       assert(!ret);
2180218ea4aSZijun Zhao     }
2190218ea4aSZijun Zhao   }
2200218ea4aSZijun Zhao 
2210218ea4aSZijun Zhao   { // repeated suffix
2220218ea4aSZijun Zhao     int a[] = {8, 6, 3, 5, 1, 2};
2230218ea4aSZijun Zhao     int p[] = {1, 2, 1, 2};
224*f73050e7SLouis Dionne     {
2250218ea4aSZijun Zhao       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
2260218ea4aSZijun Zhao       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 4)));
2270218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end());
2280218ea4aSZijun Zhao       assert(!ret);
2290218ea4aSZijun Zhao     }
2300218ea4aSZijun Zhao     {
231*f73050e7SLouis Dionne       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
232*f73050e7SLouis Dionne       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 4)));
2330218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole, suffix);
2340218ea4aSZijun Zhao       assert(!ret);
2350218ea4aSZijun Zhao     }
2360218ea4aSZijun Zhao   }
2370218ea4aSZijun Zhao 
2380218ea4aSZijun Zhao   { // check that the predicate is used
2390218ea4aSZijun Zhao     int a[]   = {5, 1, 3, 2, 7};
2400218ea4aSZijun Zhao     int p[]   = {-2, -7};
2410218ea4aSZijun Zhao     auto pred = [](int l, int r) { return l * -1 == r; };
242*f73050e7SLouis Dionne     {
2430218ea4aSZijun Zhao       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 5)));
2440218ea4aSZijun Zhao       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 2)));
2450218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole.begin(), whole.end(), suffix.begin(), suffix.end(), pred);
2460218ea4aSZijun Zhao       assert(ret);
2470218ea4aSZijun Zhao     }
2480218ea4aSZijun Zhao     {
249*f73050e7SLouis Dionne       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 5)));
250*f73050e7SLouis Dionne       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 2)));
2510218ea4aSZijun Zhao       bool ret    = std::ranges::ends_with(whole, suffix, pred);
2520218ea4aSZijun Zhao       assert(ret);
2530218ea4aSZijun Zhao     }
2540218ea4aSZijun Zhao   }
2550218ea4aSZijun Zhao 
2560218ea4aSZijun Zhao   { // check that the projections are used
2570218ea4aSZijun Zhao     int a[] = {1, 3, 15, 1, 2, 1};
2580218ea4aSZijun Zhao     int p[] = {2, 1, 2};
259*f73050e7SLouis Dionne     {
2600218ea4aSZijun Zhao       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
2610218ea4aSZijun Zhao       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
262*f73050e7SLouis Dionne       bool ret    = std::ranges::ends_with(
263*f73050e7SLouis Dionne           whole.begin(),
264*f73050e7SLouis Dionne           whole.end(),
265*f73050e7SLouis Dionne           suffix.begin(),
266*f73050e7SLouis Dionne           suffix.end(),
267*f73050e7SLouis Dionne           {},
2680218ea4aSZijun Zhao           [](int i) { return i - 3; },
2690218ea4aSZijun Zhao           [](int i) { return i * -1; });
2700218ea4aSZijun Zhao       assert(ret);
2710218ea4aSZijun Zhao     }
2720218ea4aSZijun Zhao     {
273*f73050e7SLouis Dionne       auto whole  = std::ranges::subrange(Iter1(a), Sent1(Iter1(a + 6)));
274*f73050e7SLouis Dionne       auto suffix = std::ranges::subrange(Iter2(p), Sent2(Iter2(p + 3)));
275*f73050e7SLouis Dionne       bool ret = std::ranges::ends_with(whole, suffix, {}, [](int i) { return i - 3; }, [](int i) { return i * -1; });
2760218ea4aSZijun Zhao       assert(ret);
2770218ea4aSZijun Zhao     }
2780218ea4aSZijun Zhao   }
2790218ea4aSZijun Zhao }
2800218ea4aSZijun Zhao 
2810218ea4aSZijun Zhao constexpr bool test() {
2820218ea4aSZijun Zhao   // This is to test (forward_iterator<_Iter1> || sized_sentinel_for<_Sent1, _Iter1>) condition.
2830218ea4aSZijun Zhao   types::for_each(types::cpp20_input_iterator_list<int*>{}, []<class Iter2>() {
2840218ea4aSZijun Zhao     types::for_each(types::cpp20_input_iterator_list<int*>{}, []<class Iter1>() {
2850218ea4aSZijun Zhao       if constexpr (std::forward_iterator<Iter1> && std::forward_iterator<Iter2>)
2860218ea4aSZijun Zhao         test_iterators<Iter1, Iter1, Iter2, Iter2>();
2870218ea4aSZijun Zhao       if constexpr (std::forward_iterator<Iter2>)
2880218ea4aSZijun Zhao         test_iterators<Iter1, sized_sentinel<Iter1>, Iter2, Iter2>();
2890218ea4aSZijun Zhao       if constexpr (std::forward_iterator<Iter1>)
2900218ea4aSZijun Zhao         test_iterators<Iter1, Iter1, Iter2, sized_sentinel<Iter2>>();
2910218ea4aSZijun Zhao       test_iterators<Iter1, sized_sentinel<Iter1>, Iter2, sized_sentinel<Iter2>>();
2920218ea4aSZijun Zhao     });
2930218ea4aSZijun Zhao   });
2940218ea4aSZijun Zhao 
2950218ea4aSZijun Zhao   return true;
2960218ea4aSZijun Zhao }
2970218ea4aSZijun Zhao 
2980218ea4aSZijun Zhao int main(int, char**) {
2990218ea4aSZijun Zhao   test();
3000218ea4aSZijun Zhao   static_assert(test());
3010218ea4aSZijun Zhao 
3020218ea4aSZijun Zhao   return 0;
3030218ea4aSZijun Zhao }
304