]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright David Abrahams 2004. Distributed under the Boost |
2 | // Software License, Version 1.0. (See accompanying | |
3 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
4 | ||
5 | // This is really an incomplete test; should be fleshed out. | |
6 | ||
7 | #include <boost/iterator/iterator_facade.hpp> | |
8 | #include <boost/iterator/new_iterator_tests.hpp> | |
9 | ||
10 | #include <boost/call_traits.hpp> | |
11 | #include <boost/polymorphic_cast.hpp> | |
12 | #include <boost/type_traits/is_convertible.hpp> | |
13 | #include <boost/utility/enable_if.hpp> | |
14 | ||
15 | // This is a really, really limited test so far. All we're doing | |
16 | // right now is checking that the postfix++ proxy for single-pass | |
17 | // iterators works properly. | |
18 | template <class Ref> | |
19 | class counter_iterator | |
20 | : public boost::iterator_facade< | |
21 | counter_iterator<Ref> | |
22 | , int const | |
23 | , boost::single_pass_traversal_tag | |
24 | , Ref | |
25 | > | |
26 | { | |
27 | public: | |
28 | counter_iterator() {} | |
29 | counter_iterator(int* state) : state(state) {} | |
30 | ||
31 | void increment() | |
32 | { | |
33 | ++*state; | |
34 | } | |
35 | ||
36 | Ref | |
37 | dereference() const | |
38 | { | |
39 | return *state; | |
40 | } | |
41 | ||
42 | bool equal(counter_iterator const& y) const | |
43 | { | |
44 | return *this->state == *y.state; | |
45 | } | |
46 | ||
47 | int* state; | |
48 | }; | |
49 | ||
50 | struct proxy | |
51 | { | |
52 | proxy(int& x) : state(x) {} | |
53 | ||
54 | operator int const&() const | |
55 | { | |
56 | return state; | |
57 | } | |
58 | ||
59 | int& operator=(int x) { state = x; return state; } | |
60 | ||
61 | int& state; | |
62 | }; | |
63 | ||
64 | struct value | |
65 | { | |
66 | void mutator() {} // non-const member function | |
67 | }; | |
68 | ||
69 | struct input_iter | |
70 | : boost::iterator_facade< | |
71 | input_iter | |
72 | , value | |
73 | , boost::single_pass_traversal_tag | |
74 | , value | |
75 | > | |
76 | { | |
77 | public: | |
78 | input_iter() {} | |
79 | ||
80 | void increment() | |
81 | { | |
82 | } | |
83 | value | |
84 | dereference() const | |
85 | { | |
86 | return value(); | |
87 | } | |
88 | ||
b32b8144 | 89 | bool equal(input_iter const&) const |
7c673cae FG |
90 | { |
91 | return false; | |
92 | } | |
93 | }; | |
94 | ||
95 | template <class T> | |
96 | struct wrapper | |
97 | { | |
98 | T m_x; | |
99 | explicit wrapper(typename boost::call_traits<T>::param_type x) | |
100 | : m_x(x) | |
101 | { } | |
102 | template <class U> | |
103 | wrapper(const wrapper<U>& other, | |
104 | typename boost::enable_if< boost::is_convertible<U,T> >::type* = 0) | |
105 | : m_x(other.m_x) | |
106 | { } | |
107 | }; | |
108 | ||
109 | struct iterator_with_proxy_reference | |
110 | : boost::iterator_facade< | |
111 | iterator_with_proxy_reference | |
112 | , wrapper<int> | |
113 | , boost::incrementable_traversal_tag | |
114 | , wrapper<int&> | |
115 | > | |
116 | { | |
117 | int& m_x; | |
118 | explicit iterator_with_proxy_reference(int& x) | |
119 | : m_x(x) | |
120 | { } | |
121 | ||
122 | void increment() | |
123 | { } | |
124 | wrapper<int&> dereference() const | |
125 | { return wrapper<int&>(m_x); } | |
126 | }; | |
127 | ||
128 | template <class T, class U> | |
129 | void same_type(U const&) | |
130 | { BOOST_MPL_ASSERT((boost::is_same<T,U>)); } | |
131 | ||
132 | template <class I, class A> | |
133 | struct abstract_iterator | |
134 | : boost::iterator_facade< | |
135 | abstract_iterator<I, A> | |
136 | , A & | |
137 | // In order to be value type as a reference, traversal category has | |
138 | // to satisfy least forward traversal. | |
139 | , boost::forward_traversal_tag | |
140 | , A & | |
141 | > | |
142 | { | |
143 | abstract_iterator(I iter) : iter(iter) {} | |
144 | ||
145 | void increment() | |
146 | { ++iter; } | |
147 | ||
148 | A & dereference() const | |
149 | { return *iter; } | |
150 | ||
151 | bool equal(abstract_iterator const& y) const | |
152 | { return iter == y.iter; } | |
153 | ||
154 | I iter; | |
155 | }; | |
156 | ||
157 | struct base | |
158 | { | |
159 | virtual void assign(const base &) = 0; | |
160 | virtual bool equal(const base &) const = 0; | |
161 | }; | |
162 | ||
163 | struct derived : base | |
164 | { | |
165 | derived(int state) : state(state) { } | |
166 | derived(const derived &d) : state(d.state) { } | |
167 | derived(const base &b) { derived::assign(b); } | |
168 | ||
169 | virtual void assign(const base &b) | |
170 | { | |
171 | state = boost::polymorphic_cast<const derived *>(&b)->state; | |
172 | } | |
173 | ||
174 | virtual bool equal(const base &b) const | |
175 | { | |
176 | return state == boost::polymorphic_cast<const derived *>(&b)->state; | |
177 | } | |
178 | ||
179 | int state; | |
180 | }; | |
181 | ||
182 | inline bool operator==(const base &lhs, const base &rhs) | |
183 | { | |
184 | return lhs.equal(rhs); | |
185 | } | |
186 | ||
187 | int main() | |
188 | { | |
189 | { | |
190 | int state = 0; | |
191 | boost::readable_iterator_test(counter_iterator<int const&>(&state), 0); | |
192 | state = 3; | |
193 | boost::readable_iterator_test(counter_iterator<proxy>(&state), 3); | |
194 | boost::writable_iterator_test(counter_iterator<proxy>(&state), 9, 7); | |
195 | BOOST_TEST(state == 8); | |
196 | } | |
197 | ||
198 | { | |
199 | // test for a fix to http://tinyurl.com/zuohe | |
200 | // These two lines should be equivalent (and both compile) | |
201 | input_iter p; | |
202 | (*p).mutator(); | |
203 | p->mutator(); | |
204 | ||
205 | same_type<input_iter::pointer>(p.operator->()); | |
206 | } | |
207 | ||
208 | { | |
209 | int x = 0; | |
210 | iterator_with_proxy_reference i(x); | |
211 | BOOST_TEST(x == 0); | |
212 | BOOST_TEST(i.m_x == 0); | |
213 | ++(*i).m_x; | |
214 | BOOST_TEST(x == 1); | |
215 | BOOST_TEST(i.m_x == 1); | |
216 | ++i->m_x; | |
217 | BOOST_TEST(x == 2); | |
218 | BOOST_TEST(i.m_x == 2); | |
219 | } | |
220 | ||
221 | { | |
222 | derived d(1); | |
223 | boost::readable_iterator_test(abstract_iterator<derived *, base>(&d), derived(1)); | |
224 | } | |
225 | ||
226 | return boost::report_errors(); | |
227 | } |