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-no-concepts
11 // UNSUPPORTED: gcc-10
12 
13 // template<class I2>
14 //   requires assignable_from<I&, const I2&>
15 //     constexpr counted_iterator& operator=(const counted_iterator<I2>& x);
16 
17 #include <iterator>
18 
19 #include "test_macros.h"
20 #include "test_iterators.h"
21 
22 class AssignableFromIter
23 {
24     int *it_;
25 
26 public:
27     typedef          std::input_iterator_tag                      iterator_category;
28     typedef int                                                   value_type;
29     typedef typename std::iterator_traits<int *>::difference_type difference_type;
30     typedef int *                                                 pointer;
31     typedef int &                                                 reference;
32 
33     constexpr int *base() const {return it_;}
34 
35     AssignableFromIter() = default;
36     explicit constexpr AssignableFromIter(int *it) : it_(it) {}
37     constexpr AssignableFromIter(const forward_iterator<int*>& it) : it_(it.base()) {}
38 
39     constexpr AssignableFromIter& operator=(const forward_iterator<int*> &other) {
40       it_ = other.base();
41       return *this;
42     }
43 
44     constexpr reference operator*() const {return *it_;}
45 
46     constexpr AssignableFromIter& operator++() {++it_; return *this;}
47     constexpr AssignableFromIter operator++(int)
48         {AssignableFromIter tmp(*this); ++(*this); return tmp;}
49 };
50 
51 struct InputOrOutputArchetype {
52   using difference_type = int;
53 
54   int *ptr;
55 
56   int operator*() { return *ptr; }
57   void operator++(int) { ++ptr; }
58   InputOrOutputArchetype& operator++() { ++ptr; return *this; }
59 };
60 
61 constexpr bool test() {
62   int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
63 
64   {
65     static_assert( std::is_assignable_v<std::counted_iterator<forward_iterator<int*>>,
66                                         std::counted_iterator<forward_iterator<int*>>>);
67     static_assert(!std::is_assignable_v<std::counted_iterator<forward_iterator<int*>>,
68                                         std::counted_iterator<random_access_iterator<int*>>>);
69   }
70 
71   {
72     std::counted_iterator iter1(AssignableFromIter{buffer}, 8);
73     std::counted_iterator iter2(forward_iterator<int*>{buffer + 2}, 6);
74     assert(iter1.base().base() == buffer);
75     assert(iter1.count() == 8);
76     std::counted_iterator<AssignableFromIter>& result = (iter1 = iter2);
77     assert(&result == &iter1);
78     assert(iter1.base().base() == buffer + 2);
79     assert(iter1.count() == 6);
80 
81     ASSERT_SAME_TYPE(decltype(iter1 = iter2), std::counted_iterator<AssignableFromIter>&);
82   }
83   {
84     std::counted_iterator iter1(AssignableFromIter{buffer}, 8);
85     const std::counted_iterator iter2(forward_iterator<int*>{buffer + 2}, 6);
86     assert(iter1.base().base() == buffer);
87     assert(iter1.count() == 8);
88     std::counted_iterator<AssignableFromIter>& result = (iter1 = iter2);
89     assert(&result == &iter1);
90     assert(iter1.base().base() == buffer + 2);
91     assert(iter1.count() == 6);
92 
93     ASSERT_SAME_TYPE(decltype(iter1 = iter2), std::counted_iterator<AssignableFromIter>&);
94   }
95 
96   {
97     std::counted_iterator iter1(InputOrOutputArchetype{buffer}, 8);
98     std::counted_iterator iter2(InputOrOutputArchetype{buffer + 2}, 6);
99     assert(iter1.base().ptr == buffer);
100     assert(iter1.count() == 8);
101     std::counted_iterator<InputOrOutputArchetype>& result = (iter1 = iter2);
102     assert(&result == &iter1);
103     assert(iter1.base().ptr == buffer + 2);
104     assert(iter1.count() == 6);
105 
106     ASSERT_SAME_TYPE(decltype(iter1 = iter2), std::counted_iterator<InputOrOutputArchetype>&);
107   }
108   {
109     std::counted_iterator iter1(InputOrOutputArchetype{buffer}, 8);
110     const std::counted_iterator iter2(InputOrOutputArchetype{buffer + 2}, 6);
111     assert(iter1.base().ptr == buffer);
112     assert(iter1.count() == 8);
113     std::counted_iterator<InputOrOutputArchetype>& result = (iter1 = iter2);
114     assert(&result == &iter1);
115     assert(iter1.base().ptr == buffer + 2);
116     assert(iter1.count() == 6);
117 
118     ASSERT_SAME_TYPE(decltype(iter1 = iter2), std::counted_iterator<InputOrOutputArchetype>&);
119   }
120 
121   return true;
122 }
123 
124 int main(int, char**) {
125   test();
126   static_assert(test());
127 
128   return 0;
129 }
130