mirror of
https://github.com/boostorg/type_erasure.git
synced 2026-01-19 04:42:14 +00:00
117 lines
3.4 KiB
C++
117 lines
3.4 KiB
C++
// 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/tuple.hpp>
|
|
#include <boost/mpl/vector.hpp>
|
|
#include <iostream>
|
|
|
|
namespace mpl = boost::mpl;
|
|
using namespace boost::type_erasure;
|
|
|
|
void multi1() {
|
|
//[multi1
|
|
/*`
|
|
Operations can have more than one __any argument.
|
|
Let's use binary addition as an example.
|
|
*/
|
|
typedef any<
|
|
mpl::vector<
|
|
copy_constructible<>,
|
|
typeid_<>,
|
|
addable<>,
|
|
ostreamable<>
|
|
>
|
|
> any_type;
|
|
any_type x(10);
|
|
any_type y(7);
|
|
any_type z(x + y);
|
|
std::cout << z << std::endl; // prints 17
|
|
/*`
|
|
This is /not/ a multimethod. The underlying types of the
|
|
arguments of `+` must be the same or the behavior is undefined.
|
|
This example is correct because the arguments both hold
|
|
`int`'s.
|
|
|
|
[note Adding __relaxed leads an exception rather than undefined
|
|
behavior if the argument types are wrong.]
|
|
*/
|
|
//]
|
|
}
|
|
|
|
void multi2() {
|
|
//[multi2
|
|
/*`
|
|
__addable`<>` requires the types of the arguments to be exactly
|
|
the same. This doesn't cover all uses of addition though. For
|
|
example, pointer arithmetic takes a pointer and an integer and
|
|
returns a pointer. We can capture this kind of relationship among
|
|
several types by identifying each type involved with a placeholder.
|
|
We'll let the placeholder `_a` represent the pointer and the
|
|
placeholder `_b` represent the integer.
|
|
*/
|
|
|
|
int array[5];
|
|
|
|
typedef mpl::vector<
|
|
copy_constructible<_a>,
|
|
copy_constructible<_b>,
|
|
typeid_<_a>,
|
|
addable<_a, _b, _a>
|
|
> requirements;
|
|
|
|
/*`
|
|
Our new concept, `addable<_a, _b, _a>` captures the
|
|
rules of pointer addition: `_a + _b -> _a`.
|
|
|
|
Also, we can no longer capture the variables
|
|
independently.
|
|
``
|
|
any<requirements, _a> ptr(&array[0]); // illegal
|
|
``
|
|
This doesn't work because the library needs
|
|
to know the type that _b binds to when it
|
|
captures the concept bindings. We need to
|
|
specify the bindings of both placeholders
|
|
when we construct the __any.
|
|
*/
|
|
|
|
typedef mpl::map<mpl::pair<_a, int*>, mpl::pair<_b, int> > types;
|
|
any<requirements, _a> ptr(&array[0], make_binding<types>());
|
|
any<requirements, _b> idx(2, make_binding<types>());
|
|
any<requirements, _a> x(ptr + idx);
|
|
// x now holds array + 2
|
|
|
|
/*`
|
|
Now that the arguments of `+` aren't the same type,
|
|
we require that both arguments agree that `_a` maps
|
|
to `int*` and that `_b` maps to `int`.
|
|
|
|
We can also use __tuple to avoid having to
|
|
write out the map out explicitly. __tuple is
|
|
just a convenience class that combines the
|
|
placeholder bindings it gets from all its arguments.
|
|
*/
|
|
tuple<requirements, _a, _b> t(&array[0], 2);
|
|
any<requirements, _a> y(get<0>(t) + get<1>(t));
|
|
//]
|
|
}
|
|
|
|
|
|
//[multi
|
|
//` (For the source of the examples in this section see
|
|
//` [@boost:/libs/type_erasure/example/multi.cpp multi.cpp])
|
|
//` [multi1]
|
|
//` [multi2]
|
|
//]
|