iterator_facade.cpp 4.7 KB

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