custom.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  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/concept_interface.hpp>
  12. #include <boost/type_erasure/rebind_any.hpp>
  13. #include <vector>
  14. namespace mpl = boost::mpl;
  15. using namespace boost::type_erasure;
  16. //[custom1
  17. /*`
  18. Earlier, we used __BOOST_TYPE_ERASURE_MEMBER to define
  19. a concept for containers that support `push_back`. Sometimes
  20. this interface isn't flexible enough, however. The library
  21. also provides a lower level interface that gives full
  22. control of the behavior. Let's take a look at what we
  23. would need in order to define `has_push_back.` First,
  24. we need to define the `has_push_back` template itself. We'll
  25. give it two template parameters, one for the container
  26. and one for the element type. This template must have
  27. a static member function called apply which is used
  28. to execute the operation.
  29. */
  30. template<class C, class T>
  31. struct has_push_back
  32. {
  33. static void apply(C& cont, const T& arg) { cont.push_back(arg); }
  34. };
  35. //]
  36. //[custom3
  37. /*`
  38. Our second task is to customize __any so that we can call `c.push_back(10)`.
  39. We do this by specializing __concept_interface.
  40. The first argument is `has_push_back`, since we want to inject a member
  41. into every __any that uses the `has_push_back` concept. The second argument,
  42. `Base`, is used by the library to chain multiple uses of __concept_interface
  43. together. We have to inherit from it publicly. `Base` is also used
  44. to get access to the full __any type. The third argument is the placeholder
  45. that represents this any. If someone used `push_back<_c, _b>`,
  46. we only want to insert a `push_back` member in the container,
  47. not the value type. Thus, the third argument is the container
  48. placeholder.
  49. When we define `push_back` the argument type uses the metafunction
  50. __as_param. This is just to handle the case where `T` is a
  51. placeholder. If `T` is not a placeholder, then the metafunction
  52. just returns its argument, `const T&`, unchanged.
  53. */
  54. namespace boost {
  55. namespace type_erasure {
  56. template<class C, class T, class Base>
  57. struct concept_interface<has_push_back<C, T>, Base, C> : Base
  58. {
  59. void push_back(typename as_param<Base, const T&>::type arg)
  60. { call(has_push_back<C, T>(), *this, arg); }
  61. };
  62. }
  63. }
  64. //]
  65. void custom2() {
  66. //[custom2
  67. /*`
  68. Now, we can use this in an __any using
  69. __call to dispatch the operation.
  70. */
  71. std::vector<int> vec;
  72. any<has_push_back<_self, int>, _self&> c(vec);
  73. int i = 10;
  74. call(has_push_back<_self, int>(), c, i);
  75. // vec is [10].
  76. //]
  77. }
  78. void custom4() {
  79. //[custom4
  80. /*`
  81. Our example now becomes
  82. */
  83. std::vector<int> vec;
  84. any<has_push_back<_self, int>, _self&> c(vec);
  85. c.push_back(10);
  86. /*`
  87. which is what we want.
  88. */
  89. //]
  90. }
  91. //[custom
  92. //` (For the source of the examples in this section see
  93. //` [@boost:/libs/type_erasure/example/custom.cpp custom.cpp])
  94. //` [custom1]
  95. //` [custom2]
  96. //` [custom3]
  97. //` [custom4]
  98. //]