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]
//]
|