basic.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // Boost.TypeErasure library
  2. //
  3. // Copyright 2011 Steven Watanabe
  4. //
  5. // Distributed under the Boost Software License Version 1.0. (See
  6. // accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //
  9. // $Id$
  10. #include <boost/type_erasure/any.hpp>
  11. #include <boost/type_erasure/any_cast.hpp>
  12. #include <boost/type_erasure/builtin.hpp>
  13. #include <boost/type_erasure/operators.hpp>
  14. #include <boost/type_erasure/member.hpp>
  15. #include <boost/type_erasure/free.hpp>
  16. #include <boost/mpl/vector.hpp>
  17. #include <iostream>
  18. #include <vector>
  19. namespace mpl = boost::mpl;
  20. using namespace boost::type_erasure;
  21. void basic1() {
  22. //[basic1
  23. /*`
  24. The main class in the library is __any. An __any can
  25. store objects that meet whatever requirements we specify.
  26. These requirements are passed to __any as an MPL sequence.
  27. [note The MPL sequence combines multiple concepts.
  28. In the rare case when we only want a single concept, it doesn't
  29. need to be wrapped in an MPL sequence.]
  30. */
  31. any<mpl::vector<copy_constructible<>, typeid_<>, relaxed> > x(10);
  32. int i = any_cast<int>(x); // i == 10
  33. /*`
  34. __copy_constructible is a builtin concept that allows us to
  35. copy and destroy the object. __typeid_ provides run-time
  36. type information so that we can use __any_cast. __relaxed
  37. enables various useful defaults. Without __relaxed,
  38. __any supports /exactly/ what you specify and nothing else.
  39. In particular, it allows default construction and assignment of __any.
  40. */
  41. //]
  42. }
  43. void basic2() {
  44. //[basic2
  45. /*`
  46. Now, this example doesn't do very much. `x` is approximately
  47. equivalent to a [@boost:/libs/any/index.html boost::any].
  48. We can make it more interesting by adding some operators,
  49. such as `operator++` and `operator<<`.
  50. */
  51. any<
  52. mpl::vector<
  53. copy_constructible<>,
  54. typeid_<>,
  55. incrementable<>,
  56. ostreamable<>
  57. >
  58. > x(10);
  59. ++x;
  60. std::cout << x << std::endl; // prints 11
  61. //]
  62. }
  63. //[basic3
  64. /*`
  65. The library provides concepts for most C++ operators, but this
  66. obviously won't cover all use cases; we often need to
  67. define our own requirements. Let's take the `push_back`
  68. member, defined by several STL containers.
  69. */
  70. BOOST_TYPE_ERASURE_MEMBER(push_back)
  71. void append_many(any<has_push_back<void(int)>, _self&> container) {
  72. for(int i = 0; i < 10; ++i)
  73. container.push_back(i);
  74. }
  75. /*`
  76. We use the macro __BOOST_TYPE_ERASURE_MEMBER
  77. to define a concept called `has_push_back`.
  78. When we use `has_push_back`, we have to
  79. tell it the signature of the function, `void(int)`.
  80. This means that the type we store in the any
  81. has to have a member that looks like:
  82. ``
  83. void push_back(int);
  84. ``
  85. Thus, we could call `append_many` with `std::vector<int>`,
  86. `std::list<int>`, or `std::vector<long>` (because `int` is
  87. convertible to `long`), but not `std::list<std::string>`
  88. or `std::set<int>`.
  89. Also, note that `append_many` has to operate directly
  90. on its argument. It cannot make a copy. To handle this
  91. we use `_self&` as the second argument of __any. `_self`
  92. is a __placeholder. By using `_self&`, we indicate that
  93. the __any stores a reference to an external object instead of
  94. allocating its own object.
  95. */
  96. /*`
  97. Member functions can be const.
  98. */
  99. BOOST_TYPE_ERASURE_MEMBER(empty)
  100. bool is_empty(any<has_empty<bool() const>, const _self&> x) {
  101. return x.empty();
  102. }
  103. /*`
  104. For free functions, we can use the macro __BOOST_TYPE_ERASURE_FREE.
  105. */
  106. BOOST_TYPE_ERASURE_FREE(getline)
  107. std::vector<std::string> read_lines(any<has_getline<bool(_self&, std::string&)>, _self&> stream)
  108. {
  109. std::vector<std::string> result;
  110. std::string tmp;
  111. while(getline(stream, tmp))
  112. result.push_back(tmp);
  113. return result;
  114. }
  115. /*`
  116. The use of `has_getline` is very similar to `has_push_back` above.
  117. The difference is that the placeholder `_self` is passed in
  118. the function signature instead of as a separate argument.
  119. The __placeholder doesn't have to be the first argument.
  120. We could just as easily make it the second argument.
  121. */
  122. void read_line(any<has_getline<bool(std::istream&, _self&)>, _self&> str)
  123. {
  124. getline(std::cin, str);
  125. }
  126. //]
  127. //[basic
  128. //` (For the source of the examples in this section see
  129. //` [@boost:/libs/type_erasure/example/basic.cpp basic.cpp])
  130. //` [basic1]
  131. //` [basic2]
  132. //` [basic3]
  133. //]