File: custom.cpp

package info (click to toggle)
boost1.90 1.90.0-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 593,120 kB
  • sloc: cpp: 4,190,908; xml: 196,648; python: 34,618; ansic: 23,145; asm: 5,468; sh: 3,774; makefile: 1,161; perl: 1,020; sql: 728; ruby: 676; yacc: 478; java: 77; lisp: 24; csh: 6
file content (107 lines) | stat: -rw-r--r-- 3,258 bytes parent folder | download | duplicates (18)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// 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]
//]