xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp (revision 67c4033358f39adcba53e9b70bdd4799c5a306ac)
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 
11 // constexpr const iterator_t<Base>& base() const & noexcept;
12 // constexpr iterator_t<Base> base() &&;
13 
14 #include <cassert>
15 #include <ranges>
16 #include <tuple>
17 #include <type_traits>
18 #include <utility>
19 
20 #include "MoveOnly.h"
21 #include "../types.h"
22 
23 // Test Noexcept
24 template <class T>
25 concept IsBaseNoexcept =
26     requires {
27       { std::declval<T>().base() } noexcept;
28     };
29 
30 using BaseView     = std::ranges::subrange<std::tuple<int>*>;
31 using ElementsIter = std::ranges::iterator_t<std::ranges::elements_view<BaseView, 0>>;
32 
33 static_assert(IsBaseNoexcept<const ElementsIter&>);
34 static_assert(IsBaseNoexcept<ElementsIter&>);
35 static_assert(IsBaseNoexcept<const ElementsIter&&>);
36 LIBCPP_STATIC_ASSERT(!IsBaseNoexcept<ElementsIter&&>);
37 
test()38 constexpr bool test() {
39   std::tuple<int> t{5};
40 
41   // const &
42   {
43     const ElementsIter it{&t};
44     decltype(auto) base = it.base();
45     static_assert(std::is_same_v<decltype(base), std::tuple<int>* const&>);
46     assert(base == &t);
47   }
48 
49   // &
50   {
51     ElementsIter it{&t};
52     decltype(auto) base = it.base();
53     static_assert(std::is_same_v<decltype(base), std::tuple<int>* const&>);
54     assert(base == &t);
55   }
56 
57   // &&
58   {
59     ElementsIter it{&t};
60     decltype(auto) base = std::move(it).base();
61     static_assert(std::is_same_v<decltype(base), std::tuple<int>*>);
62     assert(base == &t);
63   }
64 
65   // const &&
66   {
67     const ElementsIter it{&t};
68     decltype(auto) base = std::move(it).base();
69     static_assert(std::is_same_v<decltype(base), std::tuple<int>* const&>);
70     assert(base == &t);
71   }
72 
73   // move only
74   {
75     struct MoveOnlyIter : IterBase<MoveOnlyIter> {
76       MoveOnly mo;
77     };
78     struct Sent {
79       constexpr bool operator==(const MoveOnlyIter&) const { return true; }
80     };
81 
82     using MoveOnlyElemIter =
83         std::ranges::iterator_t<std::ranges::elements_view<std::ranges::subrange<MoveOnlyIter, Sent>, 0>>;
84 
85     MoveOnlyElemIter it{MoveOnlyIter{{}, MoveOnly{5}}};
86     decltype(auto) base = std::move(it).base();
87     static_assert(std::is_same_v<decltype(base), MoveOnlyIter>);
88     assert(base.mo.get() == 5);
89   }
90 
91   return true;
92 }
93 
main(int,char **)94 int main(int, char**) {
95   test();
96   static_assert(test());
97   return 0;
98 }
99