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 // <iterator>
10 //
11 // constexpr iterator_type base() const; // Until C++20
12 // constexpr const Iterator& base() const & noexcept; // From C++20
13 // constexpr Iterator base() &&; // From C++20
14 
15 #include <iterator>
16 
17 #include <utility>
18 #include "test_iterators.h"
19 #include "test_macros.h"
20 
21 struct MoveOnlyIterator {
22   using It = int*;
23 
24   It it_;
25 
26   using iterator_category = std::input_iterator_tag;
27   using value_type = int;
28   using difference_type = std::ptrdiff_t;
29   using reference = int&;
30 
MoveOnlyIteratorMoveOnlyIterator31   TEST_CONSTEXPR explicit MoveOnlyIterator(It it) : it_(it) {}
32   MoveOnlyIterator(MoveOnlyIterator&&) = default;
33   MoveOnlyIterator& operator=(MoveOnlyIterator&&) = default;
34   MoveOnlyIterator(const MoveOnlyIterator&) = delete;
35   MoveOnlyIterator& operator=(const MoveOnlyIterator&) = delete;
36 
operator *MoveOnlyIterator37   TEST_CONSTEXPR reference operator*() const { return *it_; }
38 
operator ++MoveOnlyIterator39   TEST_CONSTEXPR_CXX14 MoveOnlyIterator& operator++() { ++it_; return *this; }
operator ++MoveOnlyIterator40   TEST_CONSTEXPR_CXX14 MoveOnlyIterator operator++(int) { return MoveOnlyIterator(it_++); }
41 
operator ==(const MoveOnlyIterator & x,const MoveOnlyIterator & y)42   friend TEST_CONSTEXPR bool operator==(const MoveOnlyIterator& x, const MoveOnlyIterator& y) {return x.it_ == y.it_;}
operator !=(const MoveOnlyIterator & x,const MoveOnlyIterator & y)43   friend TEST_CONSTEXPR bool operator!=(const MoveOnlyIterator& x, const MoveOnlyIterator& y) {return x.it_ != y.it_;}
44 
base(const MoveOnlyIterator & i)45   friend TEST_CONSTEXPR It base(const MoveOnlyIterator& i) { return i.it_; }
46 };
47 
48 #if TEST_STD_VER > 17
49 static_assert( std::input_iterator<MoveOnlyIterator>);
50 #endif
51 static_assert(!std::is_copy_constructible<MoveOnlyIterator>::value, "");
52 
53 template <class It>
test_one()54 TEST_CONSTEXPR_CXX14 void test_one() {
55   // Non-const lvalue.
56   {
57     int a[] = {1, 2, 3};
58 
59     auto i = std::move_iterator<It>(It(a));
60 #if TEST_STD_VER > 17
61     ASSERT_SAME_TYPE(decltype(i.base()), const It&);
62     ASSERT_NOEXCEPT(i.base());
63 #else
64     ASSERT_SAME_TYPE(decltype(i.base()), It);
65 #endif
66     assert(i.base() == It(a));
67 
68     ++i;
69     assert(i.base() == It(a + 1));
70   }
71 
72   // Const lvalue.
73   {
74     int a[] = {1, 2, 3};
75 
76     const auto i = std::move_iterator<It>(It(a));
77 #if TEST_STD_VER > 17
78     ASSERT_SAME_TYPE(decltype(i.base()), const It&);
79     ASSERT_NOEXCEPT(i.base());
80 #else
81     ASSERT_SAME_TYPE(decltype(i.base()), It);
82 #endif
83     assert(i.base() == It(a));
84   }
85 
86   // Rvalue.
87   {
88     int a[] = {1, 2, 3};
89 
90     auto i = std::move_iterator<It>(It(a));
91     ASSERT_SAME_TYPE(decltype(std::move(i).base()), It);
92     assert(std::move(i).base() == It(a));
93   }
94 }
95 
test()96 TEST_CONSTEXPR_CXX14 bool test() {
97   test_one<cpp17_input_iterator<int*> >();
98   test_one<forward_iterator<int*> >();
99   test_one<bidirectional_iterator<int*> >();
100   test_one<random_access_iterator<int*> >();
101   test_one<int*>();
102   test_one<const int*>();
103 #if TEST_STD_VER > 17
104   test_one<contiguous_iterator<int*>>();
105 #endif
106 
107   return true;
108 }
109 
main(int,char **)110 int main(int, char**) {
111   test();
112 #if TEST_STD_VER > 14
113   static_assert(test());
114 #endif
115 
116   return 0;
117 }
118