From: David Abrahams on

On Feb 6, 6:12 am, Mitch <besse...(a)gmail.com> wrote:
> Reading about MPL placeholders in the book C++ Template
> Metaprogramming in Chapter 3 (3.1.5 p47) and can't understand
> placeholders. The author talks about them in some detail, but doesn't
> answer basic questions.
>
> ex: typename mpl::transform<D1, D2, mpl::minus<_1, _2> >::type
>
> First off, why _1, and _2, what happened to C/C++ being zero based?

Historical reasons, mostly. The MPL placeholder names are based on the same
names used by the Boost Lambda and then the Boost/tr1 Bind libraries, which
have an analogous meaning in the runtime world.

> It's unclear why _1 works since the "first" argument is a vector_c and
> not a single element,

The first argument to the anonymous metafunction represented by
mpl::minus<_1,_2> is not a vector_c; it is an element of that vector.

> even though in 3.4.1 the author uses the
> parameters as scalar values. But lets say the minus metafunction is
> polymorphic enough to handle both cases, then it's still unclear how
> it knows which is first and which is second.

minus doesn't need to know anything special.
Transform iterates through the two input sequences in parallel, applying its
third argument to each pair of corresponding elements in the input sequence.

> Take the example:
>
> typename mpl::transform<D1, D2, mpl::minus<D1, D2> >::type
>
> This code does not work so it's clearly not a substitution.

Correct. Let me try to be really explicit.

Let's assume D1 is the sequence of types [a1,b1,c1] and D2 is the sequence of
types [a2,b2,c2]. Then mpl::transform<D1,D2,f>::type is a sequence consisting
of the elements

[mpl::apply<f,a1,b1>::type, mpl::apply<f,a2,b2>::type, mpl::apply<f,a3,b3>::type]

or more abstractly, (and simply) if you think of f as a function, it's

[f(a1,b1), f(a2,b2), f(a3,b3)]

Now when f is mpl::minus<_1,_2>, that means "stick the first argument to f in
the position where _1 appears, and the second argument to f in the position
where _2 appears." So you get a sequence consisting of

[mpl::minus<a1,b1>::type, mpl::minus<a2,b2>::type, mpl::minus<a3,b3>::type]

or more abstractly (and simply)

[a1-b1, a2-b2, a3-b3]

If f had been mpl::minus<_2,_1> it would have meant

[mpl::minus<b1,a1>::type, mpl::minus<b2,a2>::type, mpl::minus<b3,a3>::type]

> Also,
> what are the rules for the substitution? See 3.4.2 and there the
> author has nested minus inside multiplies. So what if the expression
> was complex and not simple as in the example.
>
> mpl::transform<D1, mpl::transform<D1, D2, mpl::minus<_1, _2> >::type,
> mpl::minus<_1, _2> >::type

That would be [a1-(a1-b1), a2-(a2-b2), a3-(a3-b3)]

> Things get nasty and fast. Basically the question is what does the _1
> substitute for in the two cases? The same thing or something
> different. Impossible to tell because the scoping rules are not
> described. Perhaps if it was clear how it achieved what appears to be
> useful, this would be clear, but I've read the entire chapter and how
> it does this is still unclear.
>
> Reading the library code is even worse as what's described in the book
> doesn't exist in the code. It looks like all the stuff is generated
> so you can't read it to understand it.
>
> Okay, so can anyone explain placeholders in plain and simple English.
> No need to explain the how it works, just how to use it would be a
> good starting point, like the authors should have done.

Well, we sure tried, I can tell you that, and it has worked for at least _some_
people. If you have further questions please feel free to email me directly at
dave(a)boostpro.com

--
Dave Abrahams
Boostpro Computing
http://boostpro.com

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: David Abrahams on

on Wed Mar 12 2008, gpderetta <gpderetta-AT-gmail.com> wrote:

>> Reading the library code is even worse as what's described in the book
>> doesn't exist in the code. It looks like all the stuff is generated
>> so you can't read it to understand it.
>
> MPL uses many tricks to speed up compilation and work on lesser
> compilant compilers. You are not supposed to read the source (unless
> you want to modify the library itself). Of course when you get an
> expression wrong, you get a long unreadable list of instantiation back
> traces :).

True, but that has nothing to do with the fact that parts of the library
are generated. In fact, if anything, the use of preprocessing actually
makes it practical for us to reduce instantiation depth (and thus, the
length of those backtraces), which also speeds up compilation -- one of
those tricks you mention above.

--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]