associated.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Boost.TypeErasure library
  2. //
  3. // Copyright 2012 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/deduced.hpp>
  15. #include <boost/type_erasure/same_type.hpp>
  16. #include <boost/pointee.hpp>
  17. #include <boost/mpl/vector.hpp>
  18. #include <iostream>
  19. namespace mpl = boost::mpl;
  20. using namespace boost::type_erasure;
  21. //[associated1
  22. /*`
  23. Associated types such as `typename T::value_type` or
  24. `typename std::iterator_traits<T>::reference` are
  25. quite common in template programming.
  26. Boost.TypeErasure handles them using the __deduced
  27. template. __deduced is just like an ordinary
  28. __placeholder, except that the type that it binds
  29. to is determined by calling a metafunction and
  30. does not need to be specified explicitly.
  31. For example, we can define a concept for
  32. holding an iterator, raw pointer, or
  33. smart pointer as follows.
  34. First, we define a metafunction called `pointee`
  35. defining the associated type.
  36. */
  37. template<class T>
  38. struct pointee
  39. {
  40. typedef typename mpl::eval_if<is_placeholder<T>,
  41. mpl::identity<void>,
  42. boost::pointee<T>
  43. >::type type;
  44. };
  45. /*`
  46. Note that we can't just use `boost::pointee`, because
  47. this metafunction needs to be safe to instantiate
  48. with placeholders. It doesn't matter what it returns
  49. as long as it doesn't give an error. (The library
  50. never tries to instantiate it with a placeholder, but
  51. argument dependent lookup can cause spurious instantiations.)
  52. */
  53. template<class T = _self>
  54. struct pointer :
  55. mpl::vector<
  56. copy_constructible<T>,
  57. dereferenceable<deduced<pointee<T> >&, T>
  58. >
  59. {
  60. // provide a typedef for convenience
  61. typedef deduced<pointee<T> > element_type;
  62. };
  63. //]
  64. void associated2() {
  65. //[associated2
  66. /*`
  67. Now the Concept of `x` uses two placeholders, `_self`
  68. and `pointer<>::element_type`. When we construct `x`,
  69. with an `int*`, `pointer<>::element_type` is deduced
  70. as `pointee<int*>::type` which is `int`. Thus, dereferencing
  71. `x` returns an __any that contains an `int`.
  72. */
  73. int i = 10;
  74. any<
  75. mpl::vector<
  76. pointer<>,
  77. typeid_<pointer<>::element_type>
  78. >
  79. > x(&i);
  80. int j = any_cast<int>(*x); // j == i
  81. //]
  82. }
  83. void associated3() {
  84. //[associated3
  85. /*`
  86. Sometimes we want to require that the associated
  87. type be a specific type. This can be solved using
  88. the __same_type concept. Here we create an any that
  89. can hold any pointer whose element type is `int`.
  90. */
  91. int i = 10;
  92. any<
  93. mpl::vector<
  94. pointer<>,
  95. same_type<pointer<>::element_type, int>
  96. >
  97. > x(&i);
  98. std::cout << *x << std::endl; // prints 10
  99. /*`
  100. Using __same_type like this effectively causes the library to
  101. replace all uses of `pointer<>::element_type` with `int`
  102. and validate that it is always bound to `int`.
  103. Thus, dereferencing `x` now returns an `int`.
  104. */
  105. //]
  106. }
  107. void associated4() {
  108. //[associated4
  109. /*`
  110. __same_type can also be used for two placeholders.
  111. This allows us to use a simple name instead of
  112. writing out an associated type over and over.
  113. */
  114. int i = 10;
  115. any<
  116. mpl::vector<
  117. pointer<>,
  118. same_type<pointer<>::element_type, _a>,
  119. typeid_<_a>,
  120. copy_constructible<_a>,
  121. addable<_a>,
  122. ostreamable<std::ostream, _a>
  123. >
  124. > x(&i);
  125. std::cout << (*x + *x) << std::endl; // prints 20
  126. //]
  127. }
  128. //[associated
  129. //` (For the source of the examples in this section see
  130. //` [@boost:/libs/type_erasure/example/associated.cpp associated.cpp])
  131. //` [associated1]
  132. //` [associated2]
  133. //` [associated3]
  134. //` [associated4]
  135. //]