type_erased_test.hpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. // Boost.Range library
  2. //
  3. // Copyright Neil Groves 2010. Use, modification and
  4. // distribution is subject to the Boost Software License, Version
  5. // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. #ifndef BOOST_RANGE_ADAPTOR_TEST_TYPE_ERASED_TEST_HPP
  9. #define BOOST_RANGE_ADAPTOR_TEST_TYPE_ERASED_TEST_HPP
  10. #include <boost/range/algorithm/fill.hpp>
  11. #include <boost/range/algorithm_ext/push_back.hpp>
  12. #include <boost/assign.hpp>
  13. #include <boost/test/test_tools.hpp>
  14. namespace boost_range_adaptor_type_erased_test
  15. {
  16. class MockType
  17. {
  18. public:
  19. MockType()
  20. : m_x(0)
  21. {
  22. }
  23. MockType(boost::int32_t x)
  24. : m_x(x)
  25. {
  26. }
  27. boost::int32_t get() const { return m_x; }
  28. inline bool operator==(const MockType& other) const
  29. {
  30. return m_x == other.m_x;
  31. }
  32. inline bool operator!=(const MockType& other) const
  33. {
  34. return m_x != other.m_x;
  35. }
  36. private:
  37. boost::int32_t m_x;
  38. };
  39. class MockType2 : public MockType
  40. {
  41. public:
  42. MockType2() {}
  43. MockType2(boost::int32_t x) : MockType(x) { }
  44. MockType2(const MockType& other) : MockType(other) { }
  45. };
  46. inline std::ostream& operator<<(std::ostream& out, const MockType& obj)
  47. {
  48. out << obj.get();
  49. return out;
  50. }
  51. template<class Container>
  52. void test_type_erased_impl(Container& c)
  53. {
  54. using namespace boost::adaptors;
  55. typedef typename boost::range_value<Container>::type value_type;
  56. typedef typename boost::adaptors::type_erased<> type_erased_t;
  57. std::vector<value_type> output;
  58. boost::push_back(output, boost::adaptors::type_erase(c, type_erased_t()));
  59. BOOST_CHECK_EQUAL_COLLECTIONS( output.begin(), output.end(),
  60. c.begin(), c.end() );
  61. output.clear();
  62. boost::push_back(output, c | type_erased_t());
  63. BOOST_CHECK_EQUAL_COLLECTIONS( output.begin(), output.end(),
  64. c.begin(), c.end() );
  65. }
  66. template<class Container>
  67. void test_const_and_mutable(Container& c)
  68. {
  69. test_type_erased_impl(c);
  70. const Container& const_c = c;
  71. test_type_erased_impl(const_c);
  72. }
  73. template<class Container>
  74. void test_driver()
  75. {
  76. using namespace boost::assign;
  77. typedef typename boost::range_value<Container>::type value_type;
  78. Container c;
  79. test_const_and_mutable(c);
  80. c += value_type(1);
  81. test_const_and_mutable(c);
  82. c += value_type(2);
  83. test_const_and_mutable(c);
  84. }
  85. template<
  86. class Traversal
  87. , class Container
  88. >
  89. void test_writeable(Container&, boost::single_pass_traversal_tag)
  90. {}
  91. template<
  92. class Traversal
  93. , class Container
  94. >
  95. void test_writeable(Container& source, boost::forward_traversal_tag)
  96. {
  97. using namespace boost::adaptors;
  98. typedef typename boost::range_value<Container>::type value_type;
  99. typedef typename boost::range_difference<Container>::type difference_type;
  100. typedef typename boost::range_reference<Container>::type mutable_reference_type;
  101. typedef boost::any_range<
  102. value_type
  103. , Traversal
  104. , mutable_reference_type
  105. , difference_type
  106. > mutable_any_range;
  107. mutable_any_range r = source | boost::adaptors::type_erased<>();
  108. std::vector<value_type> output_test;
  109. boost::fill(r, value_type(1));
  110. BOOST_CHECK_EQUAL( boost::distance(r), boost::distance(source) );
  111. std::vector<value_type> reference_output(source.size(), value_type(1));
  112. BOOST_CHECK_EQUAL_COLLECTIONS( reference_output.begin(), reference_output.end(),
  113. r.begin(), r.end() );
  114. }
  115. template<
  116. class Container
  117. , class Traversal
  118. , class Buffer
  119. >
  120. void test_type_erased_impl()
  121. {
  122. using namespace boost::adaptors;
  123. typedef typename boost::range_value<Container>::type value_type;
  124. typedef typename boost::any_range_type_generator<
  125. Container
  126. , boost::use_default
  127. , Traversal
  128. , boost::use_default
  129. , boost::use_default
  130. , Buffer
  131. >::type mutable_any_range;
  132. typedef typename boost::any_range_type_generator<
  133. const Container
  134. , boost::use_default
  135. , Traversal
  136. , boost::use_default
  137. , boost::use_default
  138. , Buffer
  139. >::type const_any_range;
  140. typedef boost::adaptors::type_erased<
  141. boost::use_default
  142. , Traversal
  143. , boost::use_default
  144. , boost::use_default
  145. , Buffer
  146. > type_erased_t;
  147. Container source;
  148. for (int i = 0; i < 10; ++i)
  149. source.push_back(value_type(i));
  150. mutable_any_range r(source);
  151. BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
  152. r.begin(), r.end() );
  153. r = mutable_any_range();
  154. BOOST_CHECK_EQUAL( r.empty(), true );
  155. r = source | type_erased_t();
  156. BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
  157. r.begin(), r.end() );
  158. r = mutable_any_range();
  159. r = boost::adaptors::type_erase(source, type_erased_t());
  160. BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
  161. r.begin(), r.end() );
  162. r = mutable_any_range();
  163. test_writeable<Traversal>(source, Traversal());
  164. // convert and construct a const any_range from a mutable source
  165. // range
  166. const_any_range cr(source);
  167. BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
  168. cr.begin(), cr.end() );
  169. // assign an empty range and ensure that this correctly results
  170. // in an empty range. This is important for the validity of
  171. // the rest of the tests.
  172. cr = const_any_range();
  173. BOOST_CHECK_EQUAL( cr.empty(), true );
  174. // Test the pipe type_erased adaptor from a constant source
  175. // range to a constant any_range
  176. const Container& const_source = source;
  177. cr = const_any_range();
  178. cr = const_source | type_erased_t();
  179. BOOST_CHECK_EQUAL_COLLECTIONS( const_source.begin(), const_source.end(),
  180. cr.begin(), cr.end() );
  181. // Test the pipe type erased adaptor from a mutable source
  182. // range to a constant any_range
  183. cr = const_any_range();
  184. cr = source | type_erased_t();
  185. BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
  186. cr.begin(), cr.end() );
  187. // Use the function form of the type_erase adaptor from a constant
  188. // source range
  189. cr = const_any_range();
  190. cr = boost::adaptors::type_erase(const_source, type_erased_t());
  191. BOOST_CHECK_EQUAL_COLLECTIONS( const_source.begin(), const_source.end(),
  192. cr.begin(), cr.end() );
  193. // Assignment from mutable to const...
  194. cr = const_any_range();
  195. cr = r;
  196. BOOST_CHECK_EQUAL_COLLECTIONS( cr.begin(), cr.end(),
  197. r.begin(), r.end() );
  198. // Converting copy from mutable to const...
  199. cr = const_any_range();
  200. cr = const_any_range(r);
  201. BOOST_CHECK_EQUAL_COLLECTIONS( cr.begin(), cr.end(),
  202. r.begin(), r.end() );
  203. }
  204. template<
  205. class Container
  206. , class Traversal
  207. , class Buffer
  208. >
  209. class test_type_erased_impl_fn
  210. {
  211. public:
  212. typedef void result_type;
  213. void operator()()
  214. {
  215. test_type_erased_impl< Container, Traversal, Buffer >();
  216. }
  217. };
  218. template<
  219. class Container
  220. , class Traversal
  221. >
  222. void test_type_erased_exercise_buffer_types()
  223. {
  224. using boost::any_iterator_default_buffer;
  225. using boost::any_iterator_buffer;
  226. using boost::any_iterator_heap_only_buffer;
  227. using boost::any_iterator_stack_only_buffer;
  228. test_type_erased_impl_fn< Container, Traversal, any_iterator_default_buffer >()();
  229. test_type_erased_impl_fn< Container, Traversal, any_iterator_heap_only_buffer >()();
  230. test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<1> >()();
  231. test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<2> >()();
  232. test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<32> >()();
  233. test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<64> >()();
  234. test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<128> >()();
  235. test_type_erased_impl_fn< Container, Traversal, any_iterator_stack_only_buffer<128> >()();
  236. }
  237. } // namespace boost_range_adaptor_type_erased_test
  238. #endif // include guard