// 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 #include #include #include #include #include #include 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 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<_b, int> > types; any ptr(&array[0], make_binding()); any idx(2, make_binding()); any 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 t(&array[0], 2); any 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] //]