]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/type_erasure/example/basic.cpp
1 // Boost.TypeErasure library
3 // Copyright 2011 Steven Watanabe
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)
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>
21 namespace mpl
= boost::mpl
;
22 using namespace boost::type_erasure
;
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.
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.]
35 any
<mpl::vector
<copy_constructible
<>, typeid_
<>, relaxed
> > x(10);
36 int i
= any_cast
<int>(x
); // i == 10
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.
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<<`.
65 std::cout
<< x
<< std::endl
; // prints 11
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.
77 BOOST_TYPE_ERASURE_MEMBER((has_push_back
), push_back
, 1)
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
);
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:
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>`
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.
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.
118 BOOST_TYPE_ERASURE_MEMBER((has_empty
), empty
, 0)
119 bool is_empty(any
<has_empty
<bool(), const _self
>, const _self
&> x
) {
124 For free functions, we can use the macro __BOOST_TYPE_ERASURE_FREE.
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
)
130 std::vector
<std::string
> result
;
132 while(getline(stream
, tmp
))
133 result
.push_back(tmp
);
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.
142 The __placeholder doesn't have to be the first argument.
143 We could just as easily make it the second argument.
147 void read_line(any
<has_getline
<bool(std::istream
&, _self
&)>, _self
&> str
)
149 getline(std::cin
, str
);
155 //` (For the source of the examples in this section see
156 //` [@boost:/libs/type_erasure/example/basic.cpp basic.cpp])