123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- // Boost.TypeErasure library
- //
- // Copyright 2011 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/concept_interface.hpp>
- #include <boost/type_erasure/rebind_any.hpp>
- #include <vector>
- namespace mpl = boost::mpl;
- using namespace boost::type_erasure;
- //[custom1
- /*`
- Earlier, we used __BOOST_TYPE_ERASURE_MEMBER to define
- a concept for containers that support `push_back`. Sometimes
- this interface isn't flexible enough, however. The library
- also provides a lower level interface that gives full
- control of the behavior. Let's take a look at what we
- would need in order to define `has_push_back.` First,
- we need to define the `has_push_back` template itself. We'll
- give it two template parameters, one for the container
- and one for the element type. This template must have
- a static member function called apply which is used
- to execute the operation.
- */
- template<class C, class T>
- struct has_push_back
- {
- static void apply(C& cont, const T& arg) { cont.push_back(arg); }
- };
- //]
- //[custom3
- /*`
- Our second task is to customize __any so that we can call `c.push_back(10)`.
- We do this by specializing __concept_interface.
- The first argument is `has_push_back`, since we want to inject a member
- into every __any that uses the `has_push_back` concept. The second argument,
- `Base`, is used by the library to chain multiple uses of __concept_interface
- together. We have to inherit from it publicly. `Base` is also used
- to get access to the full __any type. The third argument is the placeholder
- that represents this any. If someone used `push_back<_c, _b>`,
- we only want to insert a `push_back` member in the container,
- not the value type. Thus, the third argument is the container
- placeholder.
- When we define `push_back` the argument type uses the metafunction
- __as_param. This is just to handle the case where `T` is a
- placeholder. If `T` is not a placeholder, then the metafunction
- just returns its argument, `const T&`, unchanged.
- */
- namespace boost {
- namespace type_erasure {
- template<class C, class T, class Base>
- struct concept_interface<has_push_back<C, T>, Base, C> : Base
- {
- void push_back(typename as_param<Base, const T&>::type arg)
- { call(has_push_back<C, T>(), *this, arg); }
- };
- }
- }
- //]
- void custom2() {
- //[custom2
- /*`
- Now, we can use this in an __any using
- __call to dispatch the operation.
- */
- std::vector<int> vec;
- any<has_push_back<_self, int>, _self&> c(vec);
- int i = 10;
- call(has_push_back<_self, int>(), c, i);
- // vec is [10].
- //]
- }
- void custom4() {
- //[custom4
- /*`
- Our example now becomes
- */
- std::vector<int> vec;
- any<has_push_back<_self, int>, _self&> c(vec);
- c.push_back(10);
- /*`
- which is what we want.
- */
- //]
- }
- //[custom
- //` (For the source of the examples in this section see
- //` [@boost:/libs/type_erasure/example/custom.cpp custom.cpp])
- //` [custom1]
- //` [custom2]
- //` [custom3]
- //` [custom4]
- //]
|