iterator_adaptor_test.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. // (C) Copyright Thomas Witt 2003.
  2. // Distributed under the Boost Software License, Version 1.0. (See
  3. // accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // See http://www.boost.org for most recent version including documentation.
  6. #include <boost/config.hpp>
  7. #include <iostream>
  8. #include <algorithm>
  9. #include <functional>
  10. #include <numeric>
  11. #include <boost/iterator/iterator_adaptor.hpp>
  12. #if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
  13. # include <boost/iterator/is_readable_iterator.hpp>
  14. # include <boost/iterator/is_lvalue_iterator.hpp>
  15. #endif
  16. #include <boost/pending/iterator_tests.hpp>
  17. # include <boost/detail/lightweight_test.hpp>
  18. #include <stdlib.h>
  19. #include <vector>
  20. #include <deque>
  21. #include <set>
  22. #include <list>
  23. #include "static_assert_same.hpp"
  24. #include <boost/iterator/detail/config_def.hpp>
  25. using boost::dummyT;
  26. typedef std::deque<int> storage;
  27. typedef std::deque<int*> pointer_deque;
  28. typedef std::set<storage::iterator> iterator_set;
  29. template <class T> struct foo;
  30. void blah(int) { }
  31. struct my_gen
  32. {
  33. typedef int result_type;
  34. my_gen() : n(0) { }
  35. int operator()() { return ++n; }
  36. int n;
  37. };
  38. template <class V>
  39. struct ptr_iterator
  40. : boost::iterator_adaptor<
  41. ptr_iterator<V>
  42. , V*
  43. , V
  44. , boost::random_access_traversal_tag
  45. #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
  46. , V&
  47. #endif
  48. >
  49. {
  50. private:
  51. typedef boost::iterator_adaptor<
  52. ptr_iterator<V>
  53. , V*
  54. , V
  55. , boost::random_access_traversal_tag
  56. #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
  57. , V&
  58. #endif
  59. > super_t;
  60. public:
  61. ptr_iterator() { }
  62. ptr_iterator(V* d) : super_t(d) { }
  63. template <class V2>
  64. ptr_iterator(
  65. const ptr_iterator<V2>& x
  66. , typename boost::enable_if_convertible<V2*, V*>::type* = 0
  67. )
  68. : super_t(x.base())
  69. {}
  70. };
  71. // Non-functional iterator for category modification checking
  72. template <class Iter, class Traversal>
  73. struct modify_traversal
  74. : boost::iterator_adaptor<
  75. modify_traversal<Iter, Traversal>
  76. , Iter
  77. , boost::use_default
  78. , Traversal
  79. >
  80. {};
  81. template <class T>
  82. struct fwd_iterator
  83. : boost::iterator_adaptor<
  84. fwd_iterator<T>
  85. , boost::forward_iterator_archetype<T>
  86. >
  87. {
  88. private:
  89. typedef boost::iterator_adaptor<
  90. fwd_iterator<T>
  91. , boost::forward_iterator_archetype<T>
  92. > super_t;
  93. public:
  94. fwd_iterator() { }
  95. fwd_iterator(boost::forward_iterator_archetype<T> d) : super_t(d) { }
  96. };
  97. template <class T>
  98. struct in_iterator
  99. : boost::iterator_adaptor<
  100. in_iterator<T>
  101. , boost::input_iterator_archetype_no_proxy<T>
  102. >
  103. {
  104. private:
  105. typedef boost::iterator_adaptor<
  106. in_iterator<T>
  107. , boost::input_iterator_archetype_no_proxy<T>
  108. > super_t;
  109. public:
  110. in_iterator() { }
  111. in_iterator(boost::input_iterator_archetype_no_proxy<T> d) : super_t(d) { }
  112. };
  113. template <class Iter>
  114. struct constant_iterator
  115. : boost::iterator_adaptor<
  116. constant_iterator<Iter>
  117. , Iter
  118. , typename std::iterator_traits<Iter>::value_type const
  119. >
  120. {
  121. typedef boost::iterator_adaptor<
  122. constant_iterator<Iter>
  123. , Iter
  124. , typename std::iterator_traits<Iter>::value_type const
  125. > base_t;
  126. constant_iterator() {}
  127. constant_iterator(Iter it)
  128. : base_t(it) {}
  129. };
  130. char (& traversal2(boost::incrementable_traversal_tag) )[1];
  131. char (& traversal2(boost::single_pass_traversal_tag ) )[2];
  132. char (& traversal2(boost::forward_traversal_tag ) )[3];
  133. char (& traversal2(boost::bidirectional_traversal_tag) )[4];
  134. char (& traversal2(boost::random_access_traversal_tag) )[5];
  135. template <class Cat>
  136. struct traversal3
  137. {
  138. static typename boost::iterator_category_to_traversal<Cat>::type x;
  139. BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(traversal2(x)));
  140. typedef char (&type)[value];
  141. };
  142. template <class Cat>
  143. typename traversal3<Cat>::type traversal(Cat);
  144. template <class Iter, class Trav>
  145. int static_assert_traversal(Iter* = 0, Trav* = 0)
  146. {
  147. typedef typename boost::iterator_category_to_traversal<
  148. BOOST_DEDUCED_TYPENAME Iter::iterator_category
  149. >::type t2;
  150. return static_assert_same<Trav,t2>::value;
  151. }
  152. int
  153. main()
  154. {
  155. dummyT array[] = { dummyT(0), dummyT(1), dummyT(2),
  156. dummyT(3), dummyT(4), dummyT(5) };
  157. const int N = sizeof(array)/sizeof(dummyT);
  158. // sanity check, if this doesn't pass the test is buggy
  159. boost::random_access_iterator_test(array, N, array);
  160. // Test the iterator_adaptor
  161. {
  162. ptr_iterator<dummyT> i(array);
  163. boost::random_access_iterator_test(i, N, array);
  164. ptr_iterator<const dummyT> j(array);
  165. boost::random_access_iterator_test(j, N, array);
  166. boost::const_nonconst_iterator_test(i, ++j);
  167. }
  168. int test;
  169. // Test the iterator_traits
  170. {
  171. // Test computation of defaults
  172. typedef ptr_iterator<int> Iter1;
  173. // don't use std::iterator_traits here to avoid VC++ problems
  174. test = static_assert_same<Iter1::value_type, int>::value;
  175. test = static_assert_same<Iter1::reference, int&>::value;
  176. test = static_assert_same<Iter1::pointer, int*>::value;
  177. test = static_assert_same<Iter1::difference_type, std::ptrdiff_t>::value;
  178. #if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
  179. BOOST_STATIC_ASSERT((boost::is_convertible<Iter1::iterator_category, std::random_access_iterator_tag>::value));
  180. #endif
  181. }
  182. {
  183. // Test computation of default when the Value is const
  184. typedef ptr_iterator<int const> Iter1;
  185. test = static_assert_same<Iter1::value_type, int>::value;
  186. test = static_assert_same<Iter1::reference, const int&>::value;
  187. #if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
  188. BOOST_STATIC_ASSERT(boost::is_readable_iterator<Iter1>::value);
  189. # ifndef BOOST_NO_LVALUE_RETURN_DETECTION
  190. BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<Iter1>::value);
  191. # endif
  192. #endif
  193. #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // borland drops constness
  194. test = static_assert_same<Iter1::pointer, int const*>::value;
  195. #endif
  196. }
  197. {
  198. // Test constant iterator idiom
  199. typedef ptr_iterator<int> BaseIter;
  200. typedef constant_iterator<BaseIter> Iter;
  201. test = static_assert_same<Iter::value_type, int>::value;
  202. test = static_assert_same<Iter::reference, int const&>::value;
  203. #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // borland drops constness
  204. test = static_assert_same<Iter::pointer, int const*>::value;
  205. #endif
  206. #ifndef BOOST_NO_LVALUE_RETURN_DETECTION
  207. BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<BaseIter>::value);
  208. BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<Iter>::value);
  209. #endif
  210. typedef modify_traversal<BaseIter, boost::incrementable_traversal_tag> IncrementableIter;
  211. static_assert_traversal<BaseIter,boost::random_access_traversal_tag>();
  212. static_assert_traversal<IncrementableIter,boost::incrementable_traversal_tag>();
  213. }
  214. // Test the iterator_adaptor
  215. {
  216. ptr_iterator<dummyT> i(array);
  217. boost::random_access_iterator_test(i, N, array);
  218. ptr_iterator<const dummyT> j(array);
  219. boost::random_access_iterator_test(j, N, array);
  220. boost::const_nonconst_iterator_test(i, ++j);
  221. }
  222. // check operator-> with a forward iterator
  223. {
  224. boost::forward_iterator_archetype<dummyT> forward_iter;
  225. typedef fwd_iterator<dummyT> adaptor_type;
  226. adaptor_type i(forward_iter);
  227. int zero = 0;
  228. if (zero) // don't do this, just make sure it compiles
  229. BOOST_TEST((*i).m_x == i->foo());
  230. }
  231. // check operator-> with an input iterator
  232. {
  233. boost::input_iterator_archetype_no_proxy<dummyT> input_iter;
  234. typedef in_iterator<dummyT> adaptor_type;
  235. adaptor_type i(input_iter);
  236. int zero = 0;
  237. if (zero) // don't do this, just make sure it compiles
  238. BOOST_TEST((*i).m_x == i->foo());
  239. }
  240. // check that base_type is correct
  241. {
  242. // Test constant iterator idiom
  243. typedef ptr_iterator<int> BaseIter;
  244. test = static_assert_same<BaseIter::base_type,int*>::value;
  245. test = static_assert_same<constant_iterator<BaseIter>::base_type,BaseIter>::value;
  246. typedef modify_traversal<BaseIter, boost::incrementable_traversal_tag> IncrementableIter;
  247. test = static_assert_same<IncrementableIter::base_type,BaseIter>::value;
  248. }
  249. std::cout << "test successful " << std::endl;
  250. (void)test;
  251. return boost::report_errors();
  252. }