iterators_test.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. // Demonstrate and test boost/operators.hpp on std::iterators --------------//
  2. // (C) Copyright Jeremy Siek 1999.
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. // See http://www.boost.org for most recent version including documentation.
  7. // Revision History
  8. // 29 May 01 Factored implementation, added comparison tests, use Test Tools
  9. // library (Daryle Walker)
  10. // 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
  11. #include <boost/core/lightweight_test.hpp>
  12. #include <boost/config.hpp> // for BOOST_STATIC_CONSTANT
  13. #include <boost/operators.hpp> // for boost::random_access_iterator_helper
  14. #include <cstddef> // for std::ptrdiff_t, std::size_t
  15. #include <cstring> // for std::strcmp
  16. #include <iostream> // for std::cout (std::endl, ends, and flush indirectly)
  17. #include <string> // for std::string
  18. #include <sstream> // for std::stringstream
  19. # ifdef BOOST_NO_STDC_NAMESPACE
  20. namespace std { using ::strcmp; }
  21. # endif
  22. // Iterator test class
  23. template <class T, class R, class P>
  24. struct test_iter
  25. : public boost::random_access_iterator_helper<
  26. test_iter<T,R,P>, T, std::ptrdiff_t, P, R>
  27. {
  28. typedef test_iter self;
  29. typedef R Reference;
  30. typedef std::ptrdiff_t Distance;
  31. public:
  32. explicit test_iter(T* i =0) : _i(i) { }
  33. test_iter(const self& x) : _i(x._i) { }
  34. self& operator=(const self& x) { _i = x._i; return *this; }
  35. Reference operator*() const { return *_i; }
  36. self& operator++() { ++_i; return *this; }
  37. self& operator--() { --_i; return *this; }
  38. self& operator+=(Distance n) { _i += n; return *this; }
  39. self& operator-=(Distance n) { _i -= n; return *this; }
  40. bool operator==(const self& x) const { return _i == x._i; }
  41. bool operator<(const self& x) const { return _i < x._i; }
  42. friend Distance operator-(const self& x, const self& y) {
  43. return x._i - y._i;
  44. }
  45. protected:
  46. P _i;
  47. };
  48. // Iterator operator testing classes
  49. class test_opr_base
  50. {
  51. protected:
  52. // Test data and types
  53. BOOST_STATIC_CONSTANT( std::size_t, fruit_length = 6u );
  54. typedef std::string fruit_array_type[ fruit_length ];
  55. static fruit_array_type fruit;
  56. }; // test_opr_base
  57. #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
  58. // A definition is required even for integral static constants
  59. const std::size_t test_opr_base::fruit_length;
  60. #endif
  61. template <typename T, typename R = T&, typename P = T*>
  62. class test_opr
  63. : public test_opr_base
  64. {
  65. typedef test_opr<T, R, P> self_type;
  66. public:
  67. // Types
  68. typedef T value_type;
  69. typedef R reference;
  70. typedef P pointer;
  71. typedef test_iter<T, R, P> iter_type;
  72. // Test controller
  73. static void master_test( char const name[] );
  74. private:
  75. // Test data
  76. static iter_type const fruit_begin;
  77. static iter_type const fruit_end;
  78. // Test parts
  79. static void post_increment_test();
  80. static void post_decrement_test();
  81. static void indirect_referral_test();
  82. static void offset_addition_test();
  83. static void reverse_offset_addition_test();
  84. static void offset_subtraction_test();
  85. static void comparison_test();
  86. static void indexing_test();
  87. }; // test_opr
  88. // Class-static data definitions
  89. test_opr_base::fruit_array_type
  90. test_opr_base::fruit = { "apple", "orange", "pear", "peach", "grape", "plum" };
  91. template <typename T, typename R, typename P>
  92. typename test_opr<T, R, P>::iter_type const
  93. test_opr<T, R, P>::fruit_begin = test_iter<T,R,P>( fruit );
  94. template <typename T, typename R, typename P>
  95. typename test_opr<T, R, P>::iter_type const
  96. test_opr<T, R, P>::fruit_end = test_iter<T,R,P>( fruit + fruit_length );
  97. // Main testing function
  98. int
  99. main()
  100. {
  101. using std::string;
  102. typedef test_opr<string, string &, string *> test1_type;
  103. typedef test_opr<string, string const &, string const *> test2_type;
  104. test1_type::master_test( "non-const string" );
  105. test2_type::master_test( "const string" );
  106. return boost::report_errors();
  107. }
  108. // Tests for all of the operators added by random_access_iterator_helper
  109. template <typename T, typename R, typename P>
  110. void
  111. test_opr<T, R, P>::master_test
  112. (
  113. char const name[]
  114. )
  115. {
  116. std::cout << "Doing test run for " << name << '.' << std::endl;
  117. post_increment_test();
  118. post_decrement_test();
  119. indirect_referral_test();
  120. offset_addition_test();
  121. reverse_offset_addition_test();
  122. offset_subtraction_test();
  123. comparison_test();
  124. indexing_test();
  125. }
  126. // Test post-increment
  127. template <typename T, typename R, typename P>
  128. void
  129. test_opr<T, R, P>::post_increment_test
  130. (
  131. )
  132. {
  133. std::cout << "\tDoing post-increment test." << std::endl;
  134. std::stringstream oss;
  135. for ( iter_type i = fruit_begin ; i != fruit_end ; )
  136. {
  137. oss << *i++ << ' ';
  138. }
  139. BOOST_TEST( oss.str() == "apple orange pear peach grape plum ");
  140. }
  141. // Test post-decrement
  142. template <typename T, typename R, typename P>
  143. void
  144. test_opr<T, R, P>::post_decrement_test
  145. (
  146. )
  147. {
  148. std::cout << "\tDoing post-decrement test." << std::endl;
  149. std::stringstream oss;
  150. for ( iter_type i = fruit_end ; i != fruit_begin ; )
  151. {
  152. i--;
  153. oss << *i << ' ';
  154. }
  155. BOOST_TEST( oss.str() == "plum grape peach pear orange apple ");
  156. }
  157. // Test indirect structure referral
  158. template <typename T, typename R, typename P>
  159. void
  160. test_opr<T, R, P>::indirect_referral_test
  161. (
  162. )
  163. {
  164. std::cout << "\tDoing indirect reference test." << std::endl;
  165. std::stringstream oss;
  166. for ( iter_type i = fruit_begin ; i != fruit_end ; ++i )
  167. {
  168. oss << i->size() << ' ';
  169. }
  170. BOOST_TEST( oss.str() == "5 6 4 5 5 4 ");
  171. }
  172. // Test offset addition
  173. template <typename T, typename R, typename P>
  174. void
  175. test_opr<T, R, P>::offset_addition_test
  176. (
  177. )
  178. {
  179. std::cout << "\tDoing offset addition test." << std::endl;
  180. std::ptrdiff_t const two = 2;
  181. std::stringstream oss;
  182. for ( iter_type i = fruit_begin ; i != fruit_end ; i = i + two )
  183. {
  184. oss << *i << ' ';
  185. }
  186. BOOST_TEST( oss.str() == "apple pear grape ");
  187. }
  188. // Test offset addition, in reverse order
  189. template <typename T, typename R, typename P>
  190. void
  191. test_opr<T, R, P>::reverse_offset_addition_test
  192. (
  193. )
  194. {
  195. std::cout << "\tDoing reverse offset addition test." << std::endl;
  196. std::ptrdiff_t const two = 2;
  197. std::stringstream oss;
  198. for ( iter_type i = fruit_begin ; i != fruit_end ; i = two + i )
  199. {
  200. oss << *i << ' ';
  201. }
  202. BOOST_TEST( oss.str() == "apple pear grape ");
  203. }
  204. // Test offset subtraction
  205. template <typename T, typename R, typename P>
  206. void
  207. test_opr<T, R, P>::offset_subtraction_test
  208. (
  209. )
  210. {
  211. std::cout << "\tDoing offset subtraction test." << std::endl;
  212. std::ptrdiff_t const two = 2;
  213. std::stringstream oss;
  214. for ( iter_type i = fruit_end ; fruit_begin < i ; )
  215. {
  216. i = i - two;
  217. if ( (fruit_begin < i) || (fruit_begin == i) )
  218. {
  219. oss << *i << ' ';
  220. }
  221. }
  222. BOOST_TEST( oss.str() == "grape pear apple ");
  223. }
  224. // Test comparisons
  225. template <typename T, typename R, typename P>
  226. void
  227. test_opr<T, R, P>::comparison_test
  228. (
  229. )
  230. {
  231. using std::cout;
  232. using std::ptrdiff_t;
  233. cout << "\tDoing comparison tests.\n\t\tPass:";
  234. for ( iter_type i = fruit_begin ; i != fruit_end ; ++i )
  235. {
  236. ptrdiff_t const i_offset = i - fruit_begin;
  237. cout << ' ' << *i << std::flush;
  238. for ( iter_type j = fruit_begin ; j != fruit_end ; ++j )
  239. {
  240. ptrdiff_t const j_offset = j - fruit_begin;
  241. BOOST_TEST( (i != j) == (i_offset != j_offset) );
  242. BOOST_TEST( (i > j) == (i_offset > j_offset) );
  243. BOOST_TEST( (i <= j) == (i_offset <= j_offset) );
  244. BOOST_TEST( (i >= j) == (i_offset >= j_offset) );
  245. }
  246. }
  247. cout << std::endl;
  248. }
  249. // Test indexing
  250. template <typename T, typename R, typename P>
  251. void
  252. test_opr<T, R, P>::indexing_test
  253. (
  254. )
  255. {
  256. std::cout << "\tDoing indexing test." << std::endl;
  257. std::stringstream oss;
  258. for ( std::size_t k = 0u ; k < fruit_length ; ++k )
  259. {
  260. oss << fruit_begin[ k ] << ' ';
  261. }
  262. BOOST_TEST( oss.str() == "apple orange pear peach grape plum ");
  263. }