• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
basic1()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 
basic2()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 
BOOST_TYPE_ERASURE_MEMBER(push_back)77 BOOST_TYPE_ERASURE_MEMBER(push_back)
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     When we use `has_push_back`, we have to
88     tell it the signature of the function, `void(int)`.
89     This means that the type we store in the any
90     has to have a member that looks like:
91 
92     ``
93     void push_back(int);
94     ``
95 
96     Thus, we could call `append_many` with `std::vector<int>`,
97     `std::list<int>`, or `std::vector<long>` (because `int` is
98     convertible to `long`), but not `std::list<std::string>`
99     or `std::set<int>`.
100 
101     Also, note that `append_many` has to operate directly
102     on its argument.  It cannot make a copy.  To handle this
103     we use `_self&` as the second argument of __any.  `_self`
104     is a __placeholder.  By using `_self&`, we indicate that
105     the __any stores a reference to an external object instead of
106     allocating its own object.
107 */
108 
109 /*`
110     Member functions can be const.
111  */
BOOST_TYPE_ERASURE_MEMBER(empty)112 BOOST_TYPE_ERASURE_MEMBER(empty)
113 bool is_empty(any<has_empty<bool() const>, const _self&> x) {
114     return x.empty();
115 }
116 
117 /*`
118     For free functions, we can use the macro __BOOST_TYPE_ERASURE_FREE.
119 */
120 
BOOST_TYPE_ERASURE_FREE(getline)121 BOOST_TYPE_ERASURE_FREE(getline)
122 std::vector<std::string> read_lines(any<has_getline<bool(_self&, std::string&)>, _self&> stream)
123 {
124     std::vector<std::string> result;
125     std::string tmp;
126     while(getline(stream, tmp))
127         result.push_back(tmp);
128     return result;
129 }
130 
131 /*`
132     The use of `has_getline` is very similar to `has_push_back` above.
133     The difference is that the placeholder `_self` is passed in
134     the function signature instead of as a separate argument.
135 
136     The __placeholder doesn't have to be the first argument.
137     We could just as easily make it the second argument.
138 */
139 
140 
read_line(any<has_getline<bool (std::istream &,_self &)>,_self &> str)141 void read_line(any<has_getline<bool(std::istream&, _self&)>, _self&> str)
142 {
143     getline(std::cin, str);
144 }
145 
146 //]
147 
148 //[basic
149 //` (For the source of the examples in this section see
150 //` [@boost:/libs/type_erasure/example/basic.cpp basic.cpp])
151 //` [basic1]
152 //` [basic2]
153 //` [basic3]
154 //]
155