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

source code of boost/libs/type_erasure/example/associated.cpp