1e53c461bSKonstantin Varlamov //===----------------------------------------------------------------------===//
2e53c461bSKonstantin Varlamov //
3e53c461bSKonstantin Varlamov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e53c461bSKonstantin Varlamov // See https://llvm.org/LICENSE.txt for license information.
5e53c461bSKonstantin Varlamov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e53c461bSKonstantin Varlamov //
7e53c461bSKonstantin Varlamov //===----------------------------------------------------------------------===//
8e53c461bSKonstantin Varlamov 
9e53c461bSKonstantin Varlamov // UNSUPPORTED: c++03, c++11, c++14, c++17
10e53c461bSKonstantin Varlamov 
11e53c461bSKonstantin Varlamov // constexpr inner-iterator& inner-iterator::operator++();
12e53c461bSKonstantin Varlamov //
13e53c461bSKonstantin Varlamov // constexpr decltype(auto) inner-iterator::operator++(int);
14e53c461bSKonstantin Varlamov 
15e53c461bSKonstantin Varlamov #include <ranges>
16e53c461bSKonstantin Varlamov 
17e53c461bSKonstantin Varlamov #include <cassert>
18e53c461bSKonstantin Varlamov #include <type_traits>
19e53c461bSKonstantin Varlamov #include "test_macros.h"
20e53c461bSKonstantin Varlamov #include "../types.h"
21e53c461bSKonstantin Varlamov 
22e53c461bSKonstantin Varlamov struct EmptyView : std::ranges::view_base {
beginEmptyView23e53c461bSKonstantin Varlamov   constexpr int* begin() const { return nullptr; }
endEmptyView24e53c461bSKonstantin Varlamov   constexpr int* end() const { return nullptr; }
sizeEmptyView25*fb855eb9SMark de Wever   constexpr static std::size_t size() { return 0; }
26e53c461bSKonstantin Varlamov };
27e53c461bSKonstantin Varlamov static_assert(std::ranges::forward_range<EmptyView>);
28e53c461bSKonstantin Varlamov static_assert(std::ranges::view<EmptyView>);
29e53c461bSKonstantin Varlamov LIBCPP_STATIC_ASSERT(std::ranges::__tiny_range<EmptyView>);
30e53c461bSKonstantin Varlamov 
test()31e53c461bSKonstantin Varlamov constexpr bool test() {
32e53c461bSKonstantin Varlamov   // Can call `inner-iterator::operator++`; `View` is a forward range.
33e53c461bSKonstantin Varlamov   {
34e53c461bSKonstantin Varlamov     SplitViewForward v("abc def", " ");
35e53c461bSKonstantin Varlamov     auto val = *v.begin();
36e53c461bSKonstantin Varlamov 
37e53c461bSKonstantin Varlamov     // ++i
38e53c461bSKonstantin Varlamov     {
39e53c461bSKonstantin Varlamov       auto i = val.begin();
40e53c461bSKonstantin Varlamov       assert(*i == 'a');
41e53c461bSKonstantin Varlamov 
42e53c461bSKonstantin Varlamov       decltype(auto) i2 = ++i;
43e53c461bSKonstantin Varlamov       static_assert(std::is_lvalue_reference_v<decltype(i2)>);
44e53c461bSKonstantin Varlamov       assert(&i2 == &i);
45e53c461bSKonstantin Varlamov       assert(*i2 == 'b');
46e53c461bSKonstantin Varlamov     }
47e53c461bSKonstantin Varlamov 
48e53c461bSKonstantin Varlamov     // i++
49e53c461bSKonstantin Varlamov     {
50e53c461bSKonstantin Varlamov       auto i = val.begin();
51e53c461bSKonstantin Varlamov       assert(*i == 'a');
52e53c461bSKonstantin Varlamov 
53e53c461bSKonstantin Varlamov       decltype(auto) i2 = i++;
54e53c461bSKonstantin Varlamov       static_assert(!std::is_reference_v<decltype(i2)>);
55e53c461bSKonstantin Varlamov       assert(*i2 == 'a');
56e53c461bSKonstantin Varlamov       assert(*i == 'b');
57e53c461bSKonstantin Varlamov     }
58e53c461bSKonstantin Varlamov   }
59e53c461bSKonstantin Varlamov 
60e53c461bSKonstantin Varlamov   // Can call `inner-iterator::operator++`; `View` is an input range.
61e53c461bSKonstantin Varlamov   {
62e53c461bSKonstantin Varlamov     // ++i
63e53c461bSKonstantin Varlamov     {
64e53c461bSKonstantin Varlamov       SplitViewInput v("abc def", ' ');
65e53c461bSKonstantin Varlamov       auto val = *v.begin();
66e53c461bSKonstantin Varlamov 
67e53c461bSKonstantin Varlamov       auto i = val.begin();
68e53c461bSKonstantin Varlamov       assert(*i == 'a');
69e53c461bSKonstantin Varlamov 
70e53c461bSKonstantin Varlamov       decltype(auto) i2 = ++i;
71e53c461bSKonstantin Varlamov       static_assert(std::is_lvalue_reference_v<decltype(i2)>);
72e53c461bSKonstantin Varlamov       assert(&i2 == &i);
73e53c461bSKonstantin Varlamov       assert(*i2 == 'b');
74e53c461bSKonstantin Varlamov     }
75e53c461bSKonstantin Varlamov 
76e53c461bSKonstantin Varlamov     // i++
77e53c461bSKonstantin Varlamov     {
78e53c461bSKonstantin Varlamov       SplitViewInput v("abc def", ' ');
79e53c461bSKonstantin Varlamov       auto val = *v.begin();
80e53c461bSKonstantin Varlamov 
81e53c461bSKonstantin Varlamov       auto i = val.begin();
82e53c461bSKonstantin Varlamov       assert(*i == 'a');
83e53c461bSKonstantin Varlamov 
84e53c461bSKonstantin Varlamov       static_assert(std::is_void_v<decltype(i++)>);
85e53c461bSKonstantin Varlamov       i++;
86e53c461bSKonstantin Varlamov       assert(*i == 'b');
87e53c461bSKonstantin Varlamov     }
88e53c461bSKonstantin Varlamov   }
89e53c461bSKonstantin Varlamov 
90e53c461bSKonstantin Varlamov   // Can call `inner-iterator::operator++`; `View` is an input range and `Pattern` is an "empty" range.
91e53c461bSKonstantin Varlamov   {
92e53c461bSKonstantin Varlamov     // ++i
93e53c461bSKonstantin Varlamov     {
94e53c461bSKonstantin Varlamov       std::ranges::lazy_split_view<InputView, EmptyView> v("a", EmptyView());
95e53c461bSKonstantin Varlamov       auto val = *v.begin();
96e53c461bSKonstantin Varlamov 
97e53c461bSKonstantin Varlamov       auto i = val.begin();
98e53c461bSKonstantin Varlamov       assert(*i.base() == 'a');
99e53c461bSKonstantin Varlamov       assert(i != std::default_sentinel);
100e53c461bSKonstantin Varlamov 
101e53c461bSKonstantin Varlamov       // The iterator doesn't move to the next character but is considered to point to the end.
102e53c461bSKonstantin Varlamov       decltype(auto) i2 = ++i;
103e53c461bSKonstantin Varlamov       assert(&i2 == &i);
104e53c461bSKonstantin Varlamov       assert(*i2.base() == 'a');
105e53c461bSKonstantin Varlamov       assert(i2 == std::default_sentinel);
106e53c461bSKonstantin Varlamov     }
107e53c461bSKonstantin Varlamov 
108e53c461bSKonstantin Varlamov     // i++
109e53c461bSKonstantin Varlamov     {
110e53c461bSKonstantin Varlamov       std::ranges::lazy_split_view<InputView, EmptyView> v("a", EmptyView());
111e53c461bSKonstantin Varlamov       auto val = *v.begin();
112e53c461bSKonstantin Varlamov 
113e53c461bSKonstantin Varlamov       auto i = val.begin();
114e53c461bSKonstantin Varlamov       assert(*i.base() == 'a');
115e53c461bSKonstantin Varlamov       assert(i != std::default_sentinel);
116e53c461bSKonstantin Varlamov 
117e53c461bSKonstantin Varlamov       // The iterator doesn't move to the next character but is considered to point to the end.
118e53c461bSKonstantin Varlamov       i++;
119e53c461bSKonstantin Varlamov       assert(*i.base() == 'a');
120e53c461bSKonstantin Varlamov       assert(i == std::default_sentinel);
121e53c461bSKonstantin Varlamov     }
122e53c461bSKonstantin Varlamov   }
123e53c461bSKonstantin Varlamov 
124e53c461bSKonstantin Varlamov   return true;
125e53c461bSKonstantin Varlamov }
126e53c461bSKonstantin Varlamov 
main(int,char **)127e53c461bSKonstantin Varlamov int main(int, char**) {
128e53c461bSKonstantin Varlamov   test();
129e53c461bSKonstantin Varlamov   static_assert(test());
130e53c461bSKonstantin Varlamov 
131e53c461bSKonstantin Varlamov   return 0;
132e53c461bSKonstantin Varlamov }
133