Boost
C++ Libraries
...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
This is an older version of Boost and was released in 2015. The current version is 1.89.0.
(For the source of the examples in this section see multi.cpp)
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 |
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));