Functions with Multiple Arguments

| Home | Libraries | People | FAQ | More

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