mirror of
https://github.com/boostorg/type_erasure.git
synced 2026-01-19 16:52:13 +00:00
108 lines
3.2 KiB
C++
108 lines
3.2 KiB
C++
// 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]
|
|
//]
|