1 // Boost.TypeErasure library
3 // Copyright 2012 Steven Watanabe
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)
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>
21 namespace mpl = boost::mpl;
22 using namespace boost::type_erasure;
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.
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.
45 typedef typename mpl::eval_if<is_placeholder<T>,
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.)
60 template<class T = _self>
63 copy_constructible<T>,
64 dereferenceable<deduced<pointee<T> >&, T>
67 // provide a typedef for convenience
68 typedef deduced<pointee<T> > element_type;
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`.
86 typeid_<pointer<>::element_type>
89 int j = any_cast<int>(*x); // j == i
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`.
105 same_type<pointer<>::element_type, int>
108 std::cout << *x << std::endl; // prints 10
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`.
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.
129 same_type<pointer<>::element_type, _a>,
131 copy_constructible<_a>,
133 ostreamable<std::ostream, _a>
136 std::cout << (*x + *x) << std::endl; // prints 20
141 //` (For the source of the examples in this section see
142 //` [@boost:/libs/type_erasure/example/associated.cpp associated.cpp])