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

PrevUpHomeNext

Functions with Multiple Arguments

(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] Note

Adding relaxed leads an exception rather than undefined behavior if the argument types are wrong.

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));


PrevUpHomeNext