blob: 9ded58294d225767bb83bc193826a60e604d892c [file] [log] [blame]
// 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]
//]