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 // UNSUPPORTED: libcpp-has-no-incomplete-ranges
11 
12 // constexpr const iterator_t<Base>& inner-iterator::base() const& noexcept;
13 //
14 // constexpr iterator_t<Base> inner-iterator::base() &&
15 //   requires forward_range<View>;
16 
17 #include <ranges>
18 
19 #include <concepts>
20 #include <utility>
21 #include "../types.h"
22 
23 static_assert( noexcept(std::declval<InnerIterForward&>().base()));
24 static_assert( noexcept(std::declval<InnerIterForward const &>().base()));
25 static_assert( noexcept(std::declval<InnerIterForward const &&>().base()));
26 static_assert( noexcept(std::declval<InnerIterInput&>().base()));
27 static_assert( noexcept(std::declval<InnerIterInput const &>().base()));
28 static_assert( noexcept(std::declval<InnerIterInput const &&>().base()));
29 
test()30 constexpr bool test() {
31   // `base` works with a forward view (two different overloads based on ref-qualification of the `inner-iterator`).
32   {
33     using BaseIter = std::ranges::iterator_t<CopyableView>;
34     CopyableView input("abc def");
35     std::ranges::lazy_split_view<CopyableView, ForwardView> v(input, " ");
36     auto i = (*v.begin()).begin();
37     const auto ci = i;
38 
39     // Note: some macOS platforms seem to have trouble deducing the type when using `std::same_as` -- use the equivalent
40     // `ASSERT_SAME_TYPE` instead.
41     {
42       decltype(auto) b = i.base();
43       ASSERT_SAME_TYPE(decltype(b), const BaseIter&);
44       assert(b == input.begin());
45     }
46 
47     {
48       decltype(auto) b = ci.base();
49       ASSERT_SAME_TYPE(decltype(b), const BaseIter&);
50       assert(b == input.begin());
51     }
52 
53     {
54       decltype(auto) b = std::move(i).base();
55       ASSERT_SAME_TYPE(decltype(b), BaseIter);
56       assert(b == input.begin());
57     }
58 
59     {
60       decltype(auto) b = std::move(ci).base();
61       ASSERT_SAME_TYPE(decltype(b), const BaseIter&);
62       assert(b == input.begin());
63     }
64   }
65 
66   // `base` works with an input view (no overloads).
67   {
68     using BaseIter = std::ranges::iterator_t<InputView>;
69     InputView input("abc def");
70     std::ranges::lazy_split_view<InputView, ForwardTinyView> v(input, ' ');
71     auto i = (*v.begin()).begin();
72     const auto ci = i;
73 
74     {
75       decltype(auto) b = i.base();
76       ASSERT_SAME_TYPE(decltype(b), const BaseIter&);
77     }
78 
79     {
80       decltype(auto) b = ci.base();
81       ASSERT_SAME_TYPE(decltype(b), const BaseIter&);
82     }
83 
84     {
85       decltype(auto) b = std::move(i).base();
86       ASSERT_SAME_TYPE(decltype(b), const BaseIter&);
87     }
88 
89     {
90       decltype(auto) b = std::move(ci).base();
91       ASSERT_SAME_TYPE(decltype(b), const BaseIter&);
92     }
93   }
94 
95   return true;
96 }
97 
main(int,char **)98 int main(int, char**) {
99   test();
100   static_assert(test());
101 
102   return 0;
103 }
104