type_erased_example.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  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. //
  9. // For more information, see http://www.boost.org/libs/range/
  10. //
  11. //[type_erased_example
  12. #include <boost/range/adaptor/type_erased.hpp>
  13. #include <boost/range/algorithm/copy.hpp>
  14. #include <boost/assign.hpp>
  15. #include <boost/foreach.hpp>
  16. #include <iterator>
  17. #include <iostream>
  18. #include <list>
  19. #include <vector>
  20. //<-
  21. #include <boost/test/test_tools.hpp>
  22. #include <boost/test/unit_test.hpp>
  23. namespace
  24. {
  25. namespace boost_range_test
  26. {
  27. namespace type_erased_example
  28. {
  29. //->
  30. // The client interface from an OO perspective merely requires a sequence
  31. // of integers that can be forward traversed
  32. typedef boost::any_range<
  33. int
  34. , boost::forward_traversal_tag
  35. , int
  36. , std::ptrdiff_t
  37. > integer_range;
  38. namespace server
  39. {
  40. void display_integers(const integer_range& rng)
  41. {
  42. boost::copy(rng,
  43. std::ostream_iterator<int>(std::cout, ","));
  44. std::cout << std::endl;
  45. }
  46. }
  47. namespace client
  48. {
  49. void run()
  50. {
  51. using namespace boost::assign;
  52. using namespace boost::adaptors;
  53. // Under most conditions one would simply use an appropriate
  54. // any_range as a function parameter. The type_erased adaptor
  55. // is often superfluous. However because the type_erased
  56. // adaptor is applied to a range, we can use default template
  57. // arguments that are generated in conjunction with the
  58. // range type to which we are applying the adaptor.
  59. std::vector<int> input;
  60. input += 1,2,3,4,5;
  61. // Note that this call is to a non-template function
  62. server::display_integers(input);
  63. std::list<int> input2;
  64. input2 += 6,7,8,9,10;
  65. // Note that this call is to the same non-tempate function
  66. server::display_integers(input2);
  67. input2.clear();
  68. input2 += 11,12,13,14,15;
  69. // Calling using the adaptor looks like this:
  70. // Notice that here I have a type_erased that would be a
  71. // bidirectional_traversal_tag, but this is convertible
  72. // to the forward_traversal_tag equivalent hence this
  73. // works.
  74. server::display_integers(input2 | type_erased<>());
  75. // However we may simply wish to define an adaptor that
  76. // takes a range and makes it into an appropriate
  77. // forward_traversal any_range...
  78. typedef boost::adaptors::type_erased<
  79. boost::use_default
  80. , boost::forward_traversal_tag
  81. > type_erased_forward;
  82. // This adaptor can turn other containers with different
  83. // value_types and reference_types into the appropriate
  84. // any_range.
  85. server::display_integers(input2 | type_erased_forward());
  86. }
  87. }
  88. //=int main(int argc, const char* argv[])
  89. //={
  90. //= client::run();
  91. //= return 0;
  92. //=}
  93. //]
  94. } // namespace type_erased_example
  95. } // namespace boost_range_test
  96. } // anonymous namespace
  97. boost::unit_test::test_suite*
  98. init_unit_test_suite(int argc, char* argv[])
  99. {
  100. boost::unit_test::test_suite* test
  101. = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.type_erased_example" );
  102. test->add( BOOST_TEST_CASE( &boost_range_test::type_erased_example::client::run) );
  103. return test;
  104. }