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