File: basic.cpp

package info (click to toggle)
boost1.90 1.90.0-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 593,156 kB
  • sloc: cpp: 4,190,642; xml: 196,648; python: 34,618; ansic: 23,145; asm: 5,468; sh: 3,776; makefile: 1,161; perl: 1,020; sql: 728; ruby: 676; yacc: 478; java: 77; lisp: 24; csh: 6
file content (154 lines) | stat: -rw-r--r-- 4,551 bytes parent folder | download | duplicates (15)
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// 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/any_cast.hpp>
#include <boost/type_erasure/builtin.hpp>
#include <boost/type_erasure/operators.hpp>
#include <boost/type_erasure/member.hpp>
#include <boost/type_erasure/free.hpp>
#include <boost/mpl/vector.hpp>
#include <iostream>
#include <vector>

namespace mpl = boost::mpl;
using namespace boost::type_erasure;

void basic1() {
    //[basic1
    /*`
        The main class in the library is __any.  An __any can
        store objects that meet whatever requirements we specify.
        These requirements are passed to __any as an MPL sequence.

        [note The MPL sequence combines multiple concepts.
        In the rare case when we only want a single concept, it doesn't
        need to be wrapped in an MPL sequence.]
    */
    any<mpl::vector<copy_constructible<>, typeid_<>, relaxed> > x(10);
    int i = any_cast<int>(x); // i == 10
    /*`
        __copy_constructible is a builtin concept that allows us to
        copy and destroy the object.  __typeid_ provides run-time
        type information so that we can use __any_cast.  __relaxed
        enables various useful defaults.  Without __relaxed,
        __any supports /exactly/ what you specify and nothing else.
        In particular, it allows default construction and assignment of __any.
     */
    //]
}

void basic2() {
    //[basic2
    /*`
        Now, this example doesn't do very much.  `x` is approximately
        equivalent to a [@boost:/libs/any/index.html boost::any].
        We can make it more interesting by adding some operators,
        such as `operator++` and `operator<<`.
    */
    any<
        mpl::vector<
            copy_constructible<>,
            typeid_<>,
            incrementable<>,
            ostreamable<>
        >
    > x(10);
    ++x;
    std::cout << x << std::endl; // prints 11
    //]
}

//[basic3
/*`
    The library provides concepts for most C++ operators, but this
    obviously won't cover all use cases;  we often need to
    define our own requirements.  Let's take the `push_back`
    member, defined by several STL containers.
*/

BOOST_TYPE_ERASURE_MEMBER(push_back)

void append_many(any<has_push_back<void(int)>, _self&> container) {
    for(int i = 0; i < 10; ++i)
        container.push_back(i);
}

/*`
    We use the macro __BOOST_TYPE_ERASURE_MEMBER 
    to define a concept called `has_push_back`.
    When we use `has_push_back`, we have to
    tell it the signature of the function, `void(int)`.
    This means that the type we store in the any
    has to have a member that looks like:

    ``
    void push_back(int);
    ``

    Thus, we could call `append_many` with `std::vector<int>`,
    `std::list<int>`, or `std::vector<long>` (because `int` is
    convertible to `long`), but not `std::list<std::string>`
    or `std::set<int>`.

    Also, note that `append_many` has to operate directly
    on its argument.  It cannot make a copy.  To handle this
    we use `_self&` as the second argument of __any.  `_self`
    is a __placeholder.  By using `_self&`, we indicate that
    the __any stores a reference to an external object instead of
    allocating its own object.
*/

/*`
    Member functions can be const.
 */
BOOST_TYPE_ERASURE_MEMBER(empty)
bool is_empty(any<has_empty<bool() const>, const _self&> x) {
    return x.empty();
}

/*`
    For free functions, we can use the macro __BOOST_TYPE_ERASURE_FREE.
*/

BOOST_TYPE_ERASURE_FREE(getline)
std::vector<std::string> read_lines(any<has_getline<bool(_self&, std::string&)>, _self&> stream)
{
    std::vector<std::string> result;
    std::string tmp;
    while(getline(stream, tmp))
        result.push_back(tmp);
    return result;
}

/*`
    The use of `has_getline` is very similar to `has_push_back` above.
    The difference is that the placeholder `_self` is passed in
    the function signature instead of as a separate argument.

    The __placeholder doesn't have to be the first argument.
    We could just as easily make it the second argument.
*/


void read_line(any<has_getline<bool(std::istream&, _self&)>, _self&> str)
{
    getline(std::cin, str);
}

//]

//[basic
//` (For the source of the examples in this section see
//` [@boost:/libs/type_erasure/example/basic.cpp basic.cpp])
//` [basic1]
//` [basic2]
//` [basic3]
//]