Imported Upstream version 1.57.0
[platform/upstream/boost.git] / libs / type_erasure / example / associated.cpp
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
21 namespace mpl = boost::mpl;
22 using 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
42 template<class T>
43 struct 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
60 template<class T = _self>
61 struct 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
73 void 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>(*x); // j == i
90     //]
91 }
92
93 void 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
118 void 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 //]