]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/type_erasure/example/basic.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / type_erasure / example / basic.cpp
1 // Boost.TypeErasure library
2 //
3 // Copyright 2011 Steven Watanabe
4 //
5 // Distributed under the Boost Software License Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // $Id$
10
11 #include <boost/type_erasure/any.hpp>
12 #include <boost/type_erasure/any_cast.hpp>
13 #include <boost/type_erasure/builtin.hpp>
14 #include <boost/type_erasure/operators.hpp>
15 #include <boost/type_erasure/member.hpp>
16 #include <boost/type_erasure/free.hpp>
17 #include <boost/mpl/vector.hpp>
18 #include <iostream>
19 #include <vector>
20
21 namespace mpl = boost::mpl;
22 using namespace boost::type_erasure;
23
24 void basic1() {
25 //[basic1
26 /*`
27 The main class in the library is __any. An __any can
28 store objects that meet whatever requirements we specify.
29 These requirements are passed to __any as an MPL sequence.
30
31 [note The MPL sequence combines multiple concepts.
32 In the rare case when we only want a single concept, it doesn't
33 need to be wrapped in an MPL sequence.]
34 */
35 any<mpl::vector<copy_constructible<>, typeid_<>, relaxed> > x(10);
36 int i = any_cast<int>(x); // i == 10
37 /*`
38 __copy_constructible is a builtin concept that allows us to
39 copy and destroy the object. __typeid_ provides run-time
40 type information so that we can use __any_cast. __relaxed
41 enables various useful defaults. Without __relaxed,
42 __any supports /exactly/ what you specify and nothing else.
43 In particular, it allows default construction and assignment of __any.
44 */
45 //]
46 }
47
48 void basic2() {
49 //[basic2
50 /*`
51 Now, this example doesn't do very much. `x` is approximately
52 equivalent to a [@boost:/libs/any/index.html boost::any].
53 We can make it more interesting by adding some operators,
54 such as `operator++` and `operator<<`.
55 */
56 any<
57 mpl::vector<
58 copy_constructible<>,
59 typeid_<>,
60 incrementable<>,
61 ostreamable<>
62 >
63 > x(10);
64 ++x;
65 std::cout << x << std::endl; // prints 11
66 //]
67 }
68
69 //[basic3
70 /*`
71 The library provides concepts for most C++ operators, but this
72 obviously won't cover all use cases; we often need to
73 define our own requirements. Let's take the `push_back`
74 member, defined by several STL containers.
75 */
76
77 BOOST_TYPE_ERASURE_MEMBER((has_push_back), push_back, 1)
78
79 void append_many(any<has_push_back<void(int)>, _self&> container) {
80 for(int i = 0; i < 10; ++i)
81 container.push_back(i);
82 }
83
84 /*`
85 We use the macro __BOOST_TYPE_ERASURE_MEMBER
86 to define a concept called `has_push_back`.
87 The second parameter is the name of the member
88 function and the last macro parameter indicates
89 the number of arguments which is `1` since `push_back`
90 is unary. When we use `has_push_back`, we have to
91 tell it the signature of the function, `void(int)`.
92 This means that the type we store in the any
93 has to have a member that looks like:
94
95 ``
96 void push_back(int);
97 ``
98
99 Thus, we could call `append_many` with `std::vector<int>`,
100 `std::list<int>`, or `std::vector<long>` (because `int` is
101 convertible to `long`), but not `std::list<std::string>`
102 or `std::set<int>`.
103
104 Also, note that `append_many` has to operate directly
105 on its argument. It cannot make a copy. To handle this
106 we use `_self&` as the second argument of __any. `_self`
107 is a __placeholder. By using `_self&`, we indicate that
108 the __any stores a reference to an external object instead of
109 allocating its own object.
110 */
111
112 /*`
113 There's actually another __placeholder here. The second
114 parameter of `has_push_back` defaults to `_self`. If
115 we wanted to define a const member function, we would
116 have to change it to `const _self`, as shown below.
117 */
118 BOOST_TYPE_ERASURE_MEMBER((has_empty), empty, 0)
119 bool is_empty(any<has_empty<bool(), const _self>, const _self&> x) {
120 return x.empty();
121 }
122
123 /*`
124 For free functions, we can use the macro __BOOST_TYPE_ERASURE_FREE.
125 */
126
127 BOOST_TYPE_ERASURE_FREE((has_getline), getline, 2)
128 std::vector<std::string> read_lines(any<has_getline<bool(_self&, std::string&)>, _self&> stream)
129 {
130 std::vector<std::string> result;
131 std::string tmp;
132 while(getline(stream, tmp))
133 result.push_back(tmp);
134 return result;
135 }
136
137 /*`
138 The use of `has_getline` is very similar to `has_push_back` above.
139 The difference is that the placeholder `_self` is passed in
140 the function signature instead of as a separate argument.
141
142 The __placeholder doesn't have to be the first argument.
143 We could just as easily make it the second argument.
144 */
145
146
147 void read_line(any<has_getline<bool(std::istream&, _self&)>, _self&> str)
148 {
149 getline(std::cin, str);
150 }
151
152 //]
153
154 //[basic
155 //` (For the source of the examples in this section see
156 //` [@boost:/libs/type_erasure/example/basic.cpp basic.cpp])
157 //` [basic1]
158 //` [basic2]
159 //` [basic3]
160 //]