123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- // 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]
- //]
|