// 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 #include #include #include 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 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 struct concept_interface, Base, C> : Base { void push_back(typename as_param::type arg) { call(has_push_back(), *this, arg); } }; } } //] void custom2() { //[custom2 /*` Now, we can use this in an __any using __call to dispatch the operation. */ std::vector vec; any, _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 vec; any, _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] //]