| // Boost.TypeErasure library |
| // |
| // Copyright 2012 Steven Watanabe |
| // |
| // Distributed under the Boost Software License Version 1.0. (See |
| // accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| // |
| // $Id$ |
| |
| #include <boost/type_erasure/any.hpp> |
| #include <boost/type_erasure/any_cast.hpp> |
| #include <boost/type_erasure/builtin.hpp> |
| #include <boost/type_erasure/operators.hpp> |
| #include <boost/type_erasure/deduced.hpp> |
| #include <boost/type_erasure/same_type.hpp> |
| #include <boost/pointee.hpp> |
| #include <boost/mpl/vector.hpp> |
| #include <iostream> |
| |
| namespace mpl = boost::mpl; |
| using namespace boost::type_erasure; |
| |
| //[associated1 |
| /*` |
| Associated types such as `typename T::value_type` or |
| `typename std::iterator_traits<T>::reference` are |
| quite common in template programming. |
| Boost.TypeErasure handles them using the __deduced |
| template. __deduced is just like an ordinary |
| __placeholder, except that the type that it binds |
| to is determined by calling a metafunction and |
| does not need to be specified explicitly. |
| |
| For example, we can define a concept for |
| holding an iterator, raw pointer, or |
| smart pointer as follows. |
| First, we define a metafunction called `pointee` |
| defining the associated type. |
| */ |
| |
| template<class T> |
| struct pointee |
| { |
| typedef typename mpl::eval_if<is_placeholder<T>, |
| mpl::identity<void>, |
| boost::pointee<T> |
| >::type type; |
| }; |
| |
| /*` |
| Note that we can't just use `boost::pointee`, because |
| this metafunction needs to be safe to instantiate |
| with placeholders. It doesn't matter what it returns |
| as long as it doesn't give an error. (The library |
| never tries to instantiate it with a placeholder, but |
| argument dependent lookup can cause spurious instantiations.) |
| */ |
| |
| template<class T = _self> |
| struct pointer : |
| mpl::vector< |
| copy_constructible<T>, |
| dereferenceable<deduced<pointee<T> >&, T> |
| > |
| { |
| // provide a typedef for convenience |
| typedef deduced<pointee<T> > element_type; |
| }; |
| |
| //] |
| |
| void associated2() { |
| //[associated2 |
| /*` |
| Now the Concept of `x` uses two placeholders, `_self` |
| and `pointer<>::element_type`. When we construct `x`, |
| with an `int*`, `pointer<>::element_type` is deduced |
| as `pointee<int*>::type` which is `int`. Thus, dereferencing |
| `x` returns an __any that contains an `int`. |
| */ |
| int i = 10; |
| any< |
| mpl::vector< |
| pointer<>, |
| typeid_<pointer<>::element_type> |
| > |
| > x(&i); |
| int j = any_cast<int>(*x); // j == i |
| //] |
| } |
| |
| void associated3() { |
| //[associated3 |
| /*` |
| Sometimes we want to require that the associated |
| type be a specific type. This can be solved using |
| the __same_type concept. Here we create an any that |
| can hold any pointer whose element type is `int`. |
| */ |
| int i = 10; |
| any< |
| mpl::vector< |
| pointer<>, |
| same_type<pointer<>::element_type, int> |
| > |
| > x(&i); |
| std::cout << *x << std::endl; // prints 10 |
| /*` |
| Using __same_type like this effectively causes the library to |
| replace all uses of `pointer<>::element_type` with `int` |
| and validate that it is always bound to `int`. |
| Thus, dereferencing `x` now returns an `int`. |
| */ |
| //] |
| } |
| |
| void associated4() { |
| //[associated4 |
| /*` |
| __same_type can also be used for two placeholders. |
| This allows us to use a simple name instead of |
| writing out an associated type over and over. |
| */ |
| int i = 10; |
| any< |
| mpl::vector< |
| pointer<>, |
| same_type<pointer<>::element_type, _a>, |
| typeid_<_a>, |
| copy_constructible<_a>, |
| addable<_a>, |
| ostreamable<std::ostream, _a> |
| > |
| > x(&i); |
| std::cout << (*x + *x) << std::endl; // prints 20 |
| //] |
| } |
| |
| //[associated |
| //` (For the source of the examples in this section see |
| //` [@boost:/libs/type_erasure/example/associated.cpp associated.cpp]) |
| //` [associated1] |
| //` [associated2] |
| //` [associated3] |
| //` [associated4] |
| //] |