multi.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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/tuple.hpp>
  15. #include <boost/mpl/vector.hpp>
  16. #include <iostream>
  17. namespace mpl = boost::mpl;
  18. using namespace boost::type_erasure;
  19. void multi1() {
  20. //[multi1
  21. /*`
  22. Operations can have more than one __any argument.
  23. Let's use binary addition as an example.
  24. */
  25. typedef any<
  26. mpl::vector<
  27. copy_constructible<>,
  28. typeid_<>,
  29. addable<>,
  30. ostreamable<>
  31. >
  32. > any_type;
  33. any_type x(10);
  34. any_type y(7);
  35. any_type z(x + y);
  36. std::cout << z << std::endl; // prints 17
  37. /*`
  38. This is /not/ a multimethod. The underlying types of the
  39. arguments of `+` must be the same or the behavior is undefined.
  40. This example is correct because the arguments both hold
  41. `int`'s.
  42. [note Adding __relaxed leads an exception rather than undefined
  43. behavior if the argument types are wrong.]
  44. */
  45. //]
  46. }
  47. void multi2() {
  48. //[multi2
  49. /*`
  50. __addable`<>` requires the types of the arguments to be exactly
  51. the same. This doesn't cover all uses of addition though. For
  52. example, pointer arithmetic takes a pointer and an integer and
  53. returns a pointer. We can capture this kind of relationship among
  54. several types by identifying each type involved with a placeholder.
  55. We'll let the placeholder `_a` represent the pointer and the
  56. placeholder `_b` represent the integer.
  57. */
  58. int array[5];
  59. typedef mpl::vector<
  60. copy_constructible<_a>,
  61. copy_constructible<_b>,
  62. typeid_<_a>,
  63. addable<_a, _b, _a>
  64. > requirements;
  65. /*`
  66. Our new concept, `addable<_a, _b, _a>` captures the
  67. rules of pointer addition: `_a + _b -> _a`.
  68. Also, we can no longer capture the variables
  69. independently.
  70. ``
  71. any<requirements, _a> ptr(&array[0]); // illegal
  72. ``
  73. This doesn't work because the library needs
  74. to know the type that _b binds to when it
  75. captures the concept bindings. We need to
  76. specify the bindings of both placeholders
  77. when we construct the __any.
  78. */
  79. typedef mpl::map<mpl::pair<_a, int*>, mpl::pair<_b, int> > types;
  80. any<requirements, _a> ptr(&array[0], make_binding<types>());
  81. any<requirements, _b> idx(2, make_binding<types>());
  82. any<requirements, _a> x(ptr + idx);
  83. // x now holds array + 2
  84. /*`
  85. Now that the arguments of `+` aren't the same type,
  86. we require that both arguments agree that `_a` maps
  87. to `int*` and that `_b` maps to `int`.
  88. We can also use __tuple to avoid having to
  89. write out the map out explicitly. __tuple is
  90. just a convenience class that combines the
  91. placeholder bindings it gets from all its arguments.
  92. */
  93. tuple<requirements, _a, _b> t(&array[0], 2);
  94. any<requirements, _a> y(get<0>(t) + get<1>(t));
  95. //]
  96. }
  97. //[multi
  98. //` (For the source of the examples in this section see
  99. //` [@boost:/libs/type_erasure/example/multi.cpp multi.cpp])
  100. //` [multi1]
  101. //` [multi2]
  102. //]