(For the source of the examples in this section see multi.cpp)
Operations can have more than one
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
+ must be the same
or the behavior is undefined. This example is correct because the arguments
<> 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; 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:
+ _b -> _a.
Also, we can no longer capture the variables independently.
any<requirements, _a> ptr(&array); // 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
typedef mpl::map<mpl::pair<_a, int*>, mpl::pair<_b, int> > types; any<requirements, _a> ptr(&array, 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
the same type, we require that both arguments agree that
_b maps to
tuple<requirements, _a, _b> t(&array, 2); any<requirements, _a> y(get<0>(t) + get<1>(t));