# Reasoning about incremental mpl entries

"Tutorial: Metafiles and Higher-Order Metaprogramming" in the Boost MPL documentation says that `transform`

you can call like this

```
typename mpl::transform<D1,D2, mpl::minus<_1,_2> >::type
```

where placeholders `_1`

and `_2`

mean that when the transformation is invoked, `BinaryOperation`

its first and second arguments will be passed to minus at the positions indicated by `_1`

and, `_2`

respectively.

I have been reading this over and over again for almost a month and I still don't get it.

What are the meanings of placeholders `_1`

and `_2`

? `D1`

and `D2`

? If so, why not write `mpl::minus<D1,D2>`

? Also considering that placeholders are defined as `typedef arg<1> _1;`

and `typedef arg<2> _2;`

and hence the original expression in my mind is

```
typename mpl::transform<D1,D2, mpl::minus<<arg<1>,<arg<2> > >::type
```

I'm sure I'm thinking the placeholders are wrong. I would appreciate some guidance here.

source to share

In fact, you are thinking about placeholders the wrong way.

`mpl::minus`

is a template in the MPL metalanguage that symbolically represents (or corresponds to) a certain high-level behavior, namely subtraction. You think of it like it's a non-meta construct like a function

```
int minus(int a, int b) { return a - b; }
```

but this is not the case. (The C ++ 11 Standard Library has something like this called `std::minus<>`

, but **not** what `mpl::minus`

it does!)

`mpl::minus`

represents a subtraction operation at a higher level of abstraction. Don't worry about a couple more paragraphs on how it's `mpl::minus`

implemented. Just think about what it represents, which is a subtraction of two things.

Oh, but what two things? So, `mpl::minus`

lets you specify these parameters as template parameters. For example,

```
mpl::minus<mpl::int_<7>, mpl::int_<3>>
```

expands to a type, the typedef member is the `type`

same as `mpl::int_<4>`

.

Okay, but in the Boost sizing example, they only have two things missing; they have consistency `D1`

and `D2`

sizes. (This is a very important point!). Subtracting sequences is not the same as subtracting whole numbers; Consider

```
auto a = std::vector<int>{ 1, 0, 0 };
auto b = std::vector<int>{ 0, 1, 0 };
auto c = (a - b); // Won't compile!
```

Similarly, in the metaspace

```
using a = mpl::vector<mpl::int_<1>, mpl::int_<0>, mpl::int_<0>>;
using b = mpl::vector<mpl::int_<1>, mpl::int_<0>, mpl::int_<0>>;
using c = mpl::minus<a,b>; // Won't compile!
```

What we want to say, in the first case,

```
auto c = std::vector<int>{};
std::transform(a.begin(), a.end(), b.begin(), std::back_inserter(c), std::minus<>{});
```

and what we want to say is in the second (meta) case,

```
using c = mpl::transform<a, b, mpl::minus>::type; // caveat: we're not done yet
```

Note that C ++ 11 `std::transform`

accepts pairs of iterators `a.begin(), a.end()`

instead of just `a`

; required `b.begin()`

, but not `b.end()`

(a flaw that is only now being corrected by the Committee ); and it modifies `c`

with the output iterator rather than returning a completely new object, for efficiency reasons. The meta version of MPL compilation takes containers `a`

and `b`

directly and returns a new container `c`

i.e. Has meaning semantics that IMHO is just easier to think about.

So the above is all right, **EXCEPT** for one tiny detail! `mpl::transform`

is actually a very general algorithm, which means it expects you to explain the details of the transformation. You said " `mpl::minus`

" which means "subtract", okay, but subtract from what? Subtract the elements of the first sequence from the elements of the second? Subtract the second item from the first? Subtract `42`

from the elements of the second sequence and discard the first part entirely?

Well, we mean "subtract the elements of the second sequence, step by step, from the first." Which we write as

```
using c = mpl::transform<a, b, mpl::minus<_1, _2>>::type;
```

We could write well

```
using c = mpl::transform<b, a, mpl::minus<_2, _1>>::type;
```

- it will mean the same thing.

This general algorithm `transform`

allows you to write complex transformations such as

```
// hide some irrelevant boilerplate behind an alias
template<typename... Ts>
using multiplies_t = mpl::multiplies<Ts...>::type;
// compute c = a^2 + 2ab + 1
using c = mpl::transform<a, b,
mpl::plus<multiplies_t< _1, _1 >, // a^2 ...
multiplies_t< mpl::int_<2>, _1, _2 >, // ... + 2ab ...
mpl::int_<1>> // ... + 1
>::type;
```

Here we can refer to the same sequence element `a`

three times using a symbol `_1`

, and `_2`

refers to the corresponding sequence element `b`

.

So that's the point of symbols `_1`

and `_2`

context `mpl::transform`

. But you are probably still wondering how they are implemented. Well, there is no magic here. They can also be implemented as

```
template<int> struct _ {};
using _1 = _<1>;
using _2 = _<2>;
```

As long as they get unique, distinguishable entities in a C ++ type system, that's all MPL really cares about.

But in reality they are actually implemented as typedefs for specializations `mpl::arg`

, which leads to a neat trick. Since it `_1`

is synonymous `mpl::arg<1>`

, we can say

```
_1::apply<A,B,C>::type is the same type as A
_2::apply<A,B,C>::type is the same type as B
...
```

and I would suggest that I `mpl::transform`

can take advantage of this fact internally.

source to share