• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
counter_iterator()28     counter_iterator() {}
counter_iterator(int * state)29     counter_iterator(int* state) : state(state) {}
30 
increment()31     void increment()
32     {
33         ++*state;
34     }
35 
36     Ref
dereference() const37     dereference() const
38     {
39         return *state;
40     }
41 
equal(counter_iterator const & y) const42     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 {
proxyproxy52     proxy(int& x) : state(x) {}
53 
operator int const&proxy54     operator int const&() const
55     {
56         return state;
57     }
58 
operator =proxy59     int& operator=(int x) { state = x; return state; }
60 
61     int& state;
62 };
63 
64 struct value
65 {
mutatorvalue66     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:
input_iterinput_iter78     input_iter() {}
79 
incrementinput_iter80     void increment()
81     {
82     }
83     value
dereferenceinput_iter84     dereference() const
85     {
86         return value();
87     }
88 
equalinput_iter89     bool equal(input_iter const&) const
90     {
91         return false;
92     }
93 };
94 
95 template <class T>
96 struct wrapper
97 {
98     T m_x;
wrapperwrapper99     explicit wrapper(typename boost::call_traits<T>::param_type x)
100         : m_x(x)
101     { }
102     template <class U>
wrapperwrapper103     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;
iterator_with_proxy_referenceiterator_with_proxy_reference118     explicit iterator_with_proxy_reference(int& x)
119         : m_x(x)
120     { }
121 
incrementiterator_with_proxy_reference122     void increment()
123     { }
dereferenceiterator_with_proxy_reference124     wrapper<int&> dereference() const
125     { return wrapper<int&>(m_x); }
126 };
127 
128 template <class T, class U>
same_type(U const &)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 {
abstract_iteratorabstract_iterator143     abstract_iterator(I iter) : iter(iter) {}
144 
incrementabstract_iterator145     void increment()
146     { ++iter; }
147 
dereferenceabstract_iterator148     A & dereference() const
149     { return *iter; }
150 
equalabstract_iterator151     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 {
derivedderived165     derived(int state) : state(state) { }
derivedderived166     derived(const derived &d) : state(d.state) { }
derivedderived167     derived(const base &b) { derived::assign(b); }
168 
assignderived169     virtual void assign(const base &b)
170     {
171         state = boost::polymorphic_cast<const derived *>(&b)->state;
172     }
173 
equalderived174     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 
operator ==(const base & lhs,const base & rhs)182 inline bool operator==(const base &lhs, const base &rhs)
183 {
184     return lhs.equal(rhs);
185 }
186 
main()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 }
228