1////
2Copyright 2015-2017 Peter Dimov
3
4Distributed under the Boost Software License, Version 1.0.
5
6See accompanying file LICENSE_1_0.txt or copy at
7http://www.boost.org/LICENSE_1_0.txt
8////
9
10# Simple {cpp}11 metaprogramming
11Peter Dimov
122015-05-26
13:toc: left
14:idprefix:
15:docinfo: shared-footer
16
17[.lead]
18__With variadic templates, parameter packs and template aliases__
19
20NOTE: I was motivated to write this after I read Eric Niebler's
21thought-provoking
22http://ericniebler.com/2014/11/13/tiny-metaprogramming-library/[Tiny
23Metaprogramming Library] article. Thanks Eric.
24
25## {cpp}11 changes the playing field
26
27The wide acceptance of http://www.boost.org/libs/mpl[Boost.MPL] made {cpp}
28metaprogramming seem a solved problem. Perhaps MPL wasn't ideal, but it was
29good enough to the point that there wasn't really a need to seek or produce
30alternatives.
31
32{cpp}11 changed the playing field. The addition of variadic templates with
33their associated parameter packs added a compile-time list of types structure
34directly into the language. Whereas before every metaprogramming library
35defined its own type list, and MPL defined several, in {cpp}11, type lists are
36as easy as
37```
38// C++11
39template<class... T> struct type_list {};
40```
41and there is hardly a reason to use anything else.
42
43Template aliases are another game changer. Previously, "metafunctions", that
44is, templates that took one type and produced another, looked like
45```
46// C++03
47template<class T> struct add_pointer { typedef T* type; };
48```
49and were used in the following manner:
50```
51// C++03
52typedef typename add_pointer<X>::type Xp;
53```
54In {cpp}11, metafunctions can be template aliases, instead of class templates:
55```
56// C++11
57template<class T> using add_pointer = T*;
58```
59The above example use then becomes
60```
61// C++11
62typedef add_pointer<X> Xp;
63```
64or, if you prefer to be seen as {cpp}11-savvy,
65```
66// C++11
67using Xp = add_pointer<X>;
68```
69This is a considerable improvement in more complex expressions:
70```
71// C++03
72typedef
73    typename add_reference<
74        typename add_const<
75            typename add_pointer<X>::type
76        >::type
77    >::type Xpcr;
78```
79```
80// C++11
81using Xpcr = add_reference<add_const<add_pointer<X>>>;
82```
83(The example also takes advantage of another {cpp}11 feature - you can now use
84`>>` to close templates without it being interpreted as a right shift.)
85
86In addition, template aliases can be passed to template template parameters:
87```
88// C++11
89template<template<class... T> class F> struct X
90{
91};
92
93X<add_pointer>; // works!
94```
95These language improvements allow for {cpp}11 metaprogramming that is
96substantially different than its idiomatic {cpp}03 equivalent. Boost.MPL is no
97longer good enough, and __something must be done__. But what?
98
99## Type lists and mp_rename
100
101Let's start with the basics. Our basic data structure will be the type list:
102```
103template<class... T> struct mp_list {};
104```
105Why the `mp_` prefix? mp obviously stands for metaprogramming, but could we not
106have used a namespace?
107
108Indeed we could have. Past experience with Boost.MPL however indicates that
109name conflicts between our metaprogramming primitives and standard identifiers
110(such as `list`) and keywords (such as `if`, `int` or `true`) will be common
111and will be a source of problems. With a prefix, we avoid all that trouble.
112
113So we have our type list and can put things into it:
114```
115using list = mp_list<int, char, float, double, void>;
116```
117but can't do anything else with it yet. We'll need a library of primitives that
118operate on ``mp_list``s. But before we get into that, let's consider another
119interesting question first.
120
121Suppose we have our library of primitives that can do things with a `mp_list`,
122but some other code hands us a type list that is not an `mp_list`, such as for
123example an `std::tuple<int, float, void*>`, or
124``http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4115.html[std::packer]<int,
125float, void*>``.
126
127Suppose we need to modify this external list of types in some manner (change
128the types into pointers, perhaps) and give back the transformed result in the
129form it was given to us, `std::tuple<int*, float*, void$$**$$>` in the first
130case and `std::packer<int*, float*, void$$**$$>` in the second.
131
132To do that, we need to first convert `std::tuple<int, float, void*>` to
133`mp_list<int, float, void*>`, apply `add_pointer` to each element obtaining
134`mp_list<int*, float*, void$$**$$>`, then convert that back to `std::tuple`.
135
136These conversion steps are a quite common occurrence, and we'll write a
137primitive that helps us perform them, called `mp_rename`. We want
138```
139mp_rename<std::tuple<int, float, void*>, mp_list>
140```
141to give us
142```
143mp_list<int, float, void*>
144```
145and conversely,
146```
147mp_rename<mp_list<int, float, void*>, std::tuple>
148```
149to give us
150```
151std::tuple<int, float, void*>
152```
153Here is the implementation of `mp_rename`:
154```
155template<class A, template<class...> class B> struct mp_rename_impl;
156
157template<template<class...> class A, class... T, template<class...> class B>
158    struct mp_rename_impl<A<T...>, B>
159{
160    using type = B<T...>;
161};
162
163template<class A, template<class...> class B>
164    using mp_rename = typename mp_rename_impl<A, B>::type;
165```
166(This pattern of a template alias forwarding to a class template doing the
167actual work is common; class templates can be specialized, whereas template
168aliases cannot.)
169
170Note that `mp_rename` does not treat any list type as special, not even
171`mp_list`; it can rename any variadic class template into any other. You could
172use it to rename `std::packer` to `std::tuple` to `std::variant` (once there is
173such a thing) and it will happily oblige.
174
175In fact, it can even rename non-variadic class templates, as in the following
176examples:
177```
178mp_rename<std::pair<int, float>, std::tuple>        // -> std::tuple<int, float>
179mp_rename<mp_list<int, float>, std::pair>           // -> std::pair<int, float>
180mp_rename<std::shared_ptr<int>, std::unique_ptr>    // -> std::unique_ptr<int>
181```
182There is a limit to the magic; `unique_ptr` can't be renamed to `shared_ptr`:
183```
184mp_rename<std::unique_ptr<int>, std::shared_ptr>    // error
185```
186because `unique_ptr<int>` is actually `unique_ptr<int,
187std::default_delete<int>>` and `mp_rename` renames it to `shared_ptr<int,
188std::default_delete<int>>`, which doesn't compile. But it still works in many
189more cases than one would naively expect at first.
190
191With conversions no longer a problem, let's move on to primitives and define a
192simple one, `mp_size`, for practice. We want `mp_size<mp_list<T$$...$$>>` to
193give us the number of elements in the list, that is, the value of the
194expression `sizeof$$...$$(T)`.
195```
196template<class L> struct mp_size_impl;
197
198template<class... T> struct mp_size_impl<mp_list<T...>>
199{
200    using type = std::integral_constant<std::size_t, sizeof...(T)>;
201};
202
203template<class L> using mp_size = typename mp_size_impl<L>::type;
204```
205This is relatively straightforward, except for the `std::integral_constant`.
206What is it and why do we need it?
207
208`std::integral_constant` is a standard {cpp}11 type that wraps an integral
209constant (that is, a compile-time constant integer value) into a type.
210
211Since metaprogramming operates on type lists, which can only hold types, it's
212convenient to represent compile-time constants as types. This allows us to
213treat lists of types and lists of values in a uniform manner. It is therefore
214idiomatic in metaprogramming to take and return types instead of values, and
215this is what we have done. If at some later point we want the actual value, we
216can use the expression `mp_size<L>::value` to retrieve it.
217
218We now have our `mp_size`, but you may have noticed that there's an interesting
219difference between `mp_size` and `mp_rename`. Whereas I made a point of
220`mp_rename` not treating `mp_list` as a special case, `mp_size` very much does:
221```
222template<class... T> struct mp_size_impl<mp_list<T...>>
223```
224Is this really necessary? Can we not use the same technique in the
225implementation of `mp_size` as we did in `mp_rename`?
226```
227template<class L> struct mp_size_impl;
228
229template<template<class...> class L, class... T> struct mp_size_impl<L<T...>>
230{
231    using type = std::integral_constant<std::size_t, sizeof...(T)>;
232};
233
234template<class L> using mp_size = typename mp_size_impl<L>::type;
235```
236Yes, we very much can, and this improvement allows us to use `mp_size` on any
237other type lists, such as `std::tuple`. It turns `mp_size` into a truly generic
238primitive.
239
240This is nice. It is so nice that I'd argue that all our metaprogramming
241primitives ought to have this property. If someone hands us a type list in the
242form of an `std::tuple`, we should be able to operate on it directly, avoiding
243the conversions to and from `mp_list`.
244
245So do we no longer have any need for `mp_rename`? Not quite. Apart from the
246fact that sometimes we really do need to rename type lists, there is another
247surprising task for which `mp_rename` is useful.
248
249To illustrate it, let me introduce the primitive `mp_length`. It's similar to
250`mp_size`, but while `mp_size` takes a type list as an argument, `mp_length`
251takes a variadic parameter pack and returns its length; or, stated differently,
252it returns its number of arguments:
253```
254template<class... T> using mp_length =
255    std::integral_constant<std::size_t, sizeof...(T)>;
256```
257How would we implement `mp_size` in terms of `mp_length`? One option is to just
258substitute the implementation of the latter into the former:
259```
260template<template<class...> class L, class... T> struct mp_size_impl<L<T...>>
261{
262    using type = mp_length<T...>;
263};
264```
265but there is another way, much less mundane. Think about what `mp_size` does.
266It takes the argument
267[subs=+quotes]
268```
269**mp_list**<int, void, float>
270```
271and returns
272[subs=+quotes]
273```
274**mp_length**<int, void, float>
275```
276Do we already have a primitive that does a similar thing?
277
278(Not much of a choice, is there?)
279
280Indeed we have, and it's called `mp_rename`.
281```
282template<class L> using mp_size = mp_rename<L, mp_length>;
283```
284I don't know about you, but I find this technique fascinating. It exploits the
285structural similarity between a list, `L<T$$...$$>`, and a metafunction "call",
286`F<T$$...$$>`, and the fact that the language sees the things the same way and
287allows us to pass the template alias `mp_length` to `mp_rename` as if it were
288an ordinary class template such as `mp_list`.
289
290(Other metaprogramming libraries provide a dedicated `apply` primitive for
291this job. `apply<F, L>` calls the metafunction `F` with the contents of the
292list `L`. We'll add an alias `mp_apply<F, L>` that calls `mp_rename<L, F>` for
293readability.)
294```
295template<template<class...> class F, class L> using mp_apply = mp_rename<L, F>;
296```
297
298## mp_transform
299
300Let's revisit the example I gave earlier - someone hands us `std::tuple<X, Y,
301Z>` and we need to compute `std::tuple<X*, Y*, Z*>`. We already have
302`add_pointer`:
303```
304template<class T> using add_pointer = T*;
305```
306so we just need to apply it to each element of the input tuple.
307
308The algorithm that takes a function and a list and applies the function to each
309element is called `transform` in Boost.MPL and the STL and `map` in functional
310languages. We'll use `transform`, for consistency with the established {cpp}
311practice (`map` is a data structure in both the STL and Boost.MPL.)
312
313We'll call our algorithm `mp_transform`, and `mp_transform<F, L>` will apply
314`F` to each element of `L` and return the result. Usually, the argument order
315is reversed and the function comes last. Our reasons to put it at the front
316will become evident later.
317
318There are many ways to implement `mp_transform`; the one we'll pick will make
319use of another primitive, `mp_push_front`. `mp_push_front<L, T>`, as its name
320implies, adds `T` as a first element in `L`:
321```
322template<class L, class T> struct mp_push_front_impl;
323
324template<template<class...> class L, class... U, class T>
325    struct mp_push_front_impl<L<U...>, T>
326{
327    using type = L<T, U...>;
328};
329
330template<class L, class T>
331    using mp_push_front = typename mp_push_front_impl<L, T>::type;
332```
333There is no reason to constrain `mp_push_front` to a single element though. In
334{cpp}11, variadic templates should be our default choice, and the
335implementation of `mp_push_front` that can take an arbitrary number of elements
336is almost identical:
337```
338template<class L, class... T> struct mp_push_front_impl;
339
340template<template<class...> class L, class... U, class... T>
341    struct mp_push_front_impl<L<U...>, T...>
342{
343    using type = L<T..., U...>;
344};
345
346template<class L, class... T>
347    using mp_push_front = typename mp_push_front_impl<L, T...>::type;
348```
349On to `mp_transform`:
350```
351template<template<class...> class F, class L> struct mp_transform_impl;
352
353template<template<class...> class F, class L>
354    using mp_transform = typename mp_transform_impl<F, L>::type;
355
356template<template<class...> class F, template<class...> class L>
357    struct mp_transform_impl<F, L<>>
358{
359    using type = L<>;
360};
361
362template<template<class...> class F, template<class...> class L, class T1, class... T>
363    struct mp_transform_impl<F, L<T1, T...>>
364{
365    using _first = F<T1>;
366    using _rest = mp_transform<F, L<T...>>;
367
368    using type = mp_push_front<_rest, _first>;
369};
370```
371This is a straightforward recursive implementation that should be familiar to
372people with functional programming background.
373
374Can we do better? It turns out that in {cpp}11, we can.
375```
376template<template<class...> class F, class L> struct mp_transform_impl;
377
378template<template<class...> class F, class L>
379    using mp_transform = typename mp_transform_impl<F, L>::type;
380
381template<template<class...> class F, template<class...> class L, class... T>
382    struct mp_transform_impl<F, L<T...>>
383{
384    using type = L<F<T>...>;
385};
386```
387Here we take advantage of the fact that pack expansion is built into the
388language, so the `F<T>$$...$$` part does all the iteration work for us.
389
390We can now solve our original challenge: given an `std::tuple` of types, return
391an `std::tuple` of pointers to these types:
392```
393using input = std::tuple<int, void, float>;
394using expected = std::tuple<int*, void*, float*>;
395
396using result = mp_transform<add_pointer, input>;
397
398static_assert( std::is_same<result, expected>::value, "" );
399```
400
401## mp_transform, part two
402
403What if we had a pair of tuples as input, and had to produce the corresponding
404tuple of pairs? For example, given
405```
406using input = std::pair<std::tuple<X1, X2, X3>, std::tuple<Y1, Y2, Y3>>;
407```
408we had to produce
409```
410using expected = std::tuple<std::pair<X1, Y1>, std::pair<X2, Y2>, std::pair<X3, Y3>>;
411```
412We need to take the two lists, represented by tuples in the input, and combine
413them pairwise by using `std::pair`. If we think of `std::pair` as a function
414`F`, this task appears very similar to `mp_transform`, except we need to use a
415binary function and two lists.
416
417Changing our unary transform algorithm into a binary one isn't hard:
418```
419template<template<class...> class F, class L1, class L2>
420    struct mp_transform2_impl;
421
422template<template<class...> class F, class L1, class L2>
423    using mp_transform2 = typename mp_transform2_impl<F, L1, L2>::type;
424
425template<template<class...> class F,
426    template<class...> class L1, class... T1,
427    template<class...> class L2, class... T2>
428    struct mp_transform2_impl<F, L1<T1...>, L2<T2...>>
429{
430    static_assert( sizeof...(T1) == sizeof...(T2),
431        "The arguments of mp_transform2 should be of the same size" );
432
433    using type = L1<F<T1,T2>...>;
434};
435```
436and we can now do
437```
438using input = std::pair<std::tuple<X1, X2, X3>, std::tuple<Y1, Y2, Y3>>;
439using expected = std::tuple<std::pair<X1, Y1>, std::pair<X2, Y2>, std::pair<X3, Y3>>;
440
441using result = mp_transform2<std::pair, input::first_type, input::second_type>;
442
443static_assert( std::is_same<result, expected>::value, "" );
444```
445again exploiting the similarity between metafunctions and ordinary class
446templates such as `std::pair`, this time in the other direction; we pass
447`std::pair` where `mp_transform2` expects a metafunction.
448
449Do we _have_ to use separate transform algorithms for each arity though? If we
450need a transform algorithm that takes a ternary function and three lists,
451should we name it `mp_transform3`? No, this is exactly why we put the function
452first. We just have to change `mp_transform` to be variadic:
453```
454template<template<class...> class F, class... L> struct mp_transform_impl;
455
456template<template<class...> class F, class... L>
457    using mp_transform = typename mp_transform_impl<F, L...>::type;
458```
459and then add the unary and binary specializations:
460```
461template<template<class...> class F, template<class...> class L, class... T>
462    struct mp_transform_impl<F, L<T...>>
463{
464    using type = L<F<T>...>;
465};
466
467template<template<class...> class F,
468    template<class...> class L1, class... T1,
469    template<class...> class L2, class... T2>
470    struct mp_transform_impl<F, L1<T1...>, L2<T2...>>
471{
472    static_assert( sizeof...(T1) == sizeof...(T2),
473        "The arguments of mp_transform should be of the same size" );
474
475    using type = L1<F<T1,T2>...>;
476};
477```
478We can also add ternary and further specializations.
479
480Is it possible to implement the truly variadic `mp_transform`, one that works
481with an arbitrary number of lists? It is in principle, and I'll show one
482possible abridged implementation here for completeness:
483```
484template<template<class...> class F, class E, class... L>
485    struct mp_transform_impl;
486
487template<template<class...> class F, class... L>
488    using mp_transform = typename mp_transform_impl<F, mp_empty<L...>, L...>::type;
489
490template<template<class...> class F, class L1, class... L>
491    struct mp_transform_impl<F, mp_true, L1, L...>
492{
493    using type = mp_clear<L1>;
494};
495
496template<template<class...> class F, class... L>
497    struct mp_transform_impl<F, mp_false, L...>
498{
499    using _first = F< typename mp_front_impl<L>::type... >;
500    using _rest = mp_transform< F, typename mp_pop_front_impl<L>::type... >;
501
502    using type = mp_push_front<_rest, _first>;
503};
504```
505but will omit the primitives that it uses. These are
506
507* `mp_true` -- an alias for `std::integral_constant<bool, true>`.
508* `mp_false` -- an alias for `std::integral_constant<bool, false>`.
509* `mp_empty<L$$...$$>` -- returns `mp_true` if all lists are empty, `mp_false`
510  otherwise.
511* `mp_clear<L>` -- returns an empty list of the same type as `L`.
512* `mp_front<L>` -- returns the first element of `L`.
513* `mp_pop_front<L>` -- returns `L` without its first element.
514
515There is one interesting difference between the recursive `mp_transform`
516implementation and the language-based one. `mp_transform<add_pointer,
517std::pair<int, float>>` works with the `F<T>$$...$$` implementation and fails
518with the recursive one, because `std::pair` is not a real type list and can
519only hold exactly two types.
520
521## The infamous tuple_cat challenge
522
523Eric Niebler, in his
524http://ericniebler.com/2014/11/13/tiny-metaprogramming-library/[Tiny
525Metaprogramming Library] article, gives the function
526http://en.cppreference.com/w/cpp/utility/tuple/tuple_cat[`std::tuple_cat`] as a
527kind of a metaprogramming challenge. `tuple_cat` is a variadic template
528function that takes a number of tuples and concatenates them into another
529`std::tuple`. This is Eric's solution:
530```
531namespace detail
532{
533    template<typename Ret, typename...Is, typename ...Ks,
534        typename Tuples>
535    Ret tuple_cat_(typelist<Is...>, typelist<Ks...>,
536        Tuples tpls)
537    {
538        return Ret{std::get<Ks::value>(
539            std::get<Is::value>(tpls))...};
540    }
541}
542
543template<typename...Tuples,
544    typename Res =
545        typelist_apply_t<
546            meta_quote<std::tuple>,
547            typelist_cat_t<typelist<as_typelist_t<Tuples>...> > > >
548Res tuple_cat(Tuples &&... tpls)
549{
550    static constexpr std::size_t N = sizeof...(Tuples);
551    // E.g. [0,0,0,2,2,2,3,3]
552    using inner =
553        typelist_cat_t<
554            typelist_transform_t<
555                typelist<as_typelist_t<Tuples>...>,
556                typelist_transform_t<
557                    as_typelist_t<make_index_sequence<N> >,
558                    meta_quote<meta_always> >,
559                meta_quote<typelist_transform_t> > >;
560    // E.g. [0,1,2,0,1,2,0,1]
561    using outer =
562        typelist_cat_t<
563            typelist_transform_t<
564                typelist<as_typelist_t<Tuples>...>,
565                meta_compose<
566                    meta_quote<as_typelist_t>,
567                    meta_quote_i<std::size_t, make_index_sequence>,
568                    meta_quote<typelist_size_t> > > >;
569    return detail::tuple_cat_<Res>(
570        inner{},
571        outer{},
572        std::forward_as_tuple(std::forward<Tuples>(tpls)...));
573}
574```
575All right, challenge accepted. Let's see what we can do.
576
577As Eric explains, this implementation relies on the clever trick of packing the
578input tuples into a tuple, creating two arrays of indices, `inner` and `outer`,
579then indexing the outer tuple with the outer indices and the result, which is
580one of our input tuples, with the inner indices.
581
582So, for example, if tuple_cat is invoked as
583```
584std::tuple<int, short, long> t1;
585std::tuple<> t2;
586std::tuple<float, double, long double> t3;
587std::tuple<void*, char*> t4;
588
589auto res = tuple_cat(t1, t2, t3, t4);
590```
591we'll create the tuple
592```
593std::tuple<std::tuple<int, short, long>, std::tuple<>,
594    std::tuple<float, double, long double>, std::tuple<void*, char*>> t{t1, t2, t3, t4};
595```
596and then extract the elements of t via
597```
598std::get<0>(std::get<0>(t)), // t1[0]
599std::get<1>(std::get<0>(t)), // t1[1]
600std::get<2>(std::get<0>(t)), // t1[2]
601std::get<0>(std::get<2>(t)), // t3[0]
602std::get<1>(std::get<2>(t)), // t3[1]
603std::get<2>(std::get<2>(t)), // t3[2]
604std::get<0>(std::get<3>(t)), // t4[0]
605std::get<1>(std::get<3>(t)), // t4[1]
606```
607(`t2` is empty, so we take nothing from it.)
608
609The first column of integers is the `outer` array, the second one - the `inner`
610array, and these are what we need to compute. But first, let's deal with the
611return type of `tuple_cat`.
612
613The return type of `tuple_cat` is just the concatenation of the arguments,
614viewed as type lists. The metaprogramming algorithm that concatenates lists is
615called
616https://ericniebler.github.io/meta/group__transformation.html[`meta::concat`]
617in Eric Niebler's https://github.com/ericniebler/meta[Meta] library, but I'll
618call it `mp_append`, after its classic Lisp name.
619
620(Lisp is today's equivalent of Latin. Educated people are supposed to have
621studied and forgotten it.)
622```
623template<class... L> struct mp_append_impl;
624
625template<class... L> using mp_append = typename mp_append_impl<L...>::type;
626
627template<> struct mp_append_impl<>
628{
629    using type = mp_list<>;
630};
631
632template<template<class...> class L, class... T> struct mp_append_impl<L<T...>>
633{
634    using type = L<T...>;
635};
636
637template<template<class...> class L1, class... T1,
638    template<class...> class L2, class... T2, class... Lr>
639    struct mp_append_impl<L1<T1...>, L2<T2...>, Lr...>
640{
641    using type = mp_append<L1<T1..., T2...>, Lr...>;
642};
643```
644That was fairly easy. There are other ways to implement `mp_append`, but this
645one demonstrates how the language does most of the work for us via pack
646expansion. This is a common theme in {cpp}11.
647
648Note how `mp_append` returns the same list type as its first argument. Of
649course, in the case in which no arguments are given, there is no first argument
650from which to take the type, so I've arbitrarily chosen to return an empty
651`mp_list`.
652
653We're now ready with the declaration of `tuple_cat`:
654```
655template<class... Tp,
656    class R = mp_append<typename std::remove_reference<Tp>::type...>>
657    R tuple_cat( Tp &&... tp );
658```
659The reason we need `remove_reference` is because of the rvalue reference
660parameters, used to implement perfect forwarding. If the argument is an lvalue,
661such as for example `t1` above, its corresponding type will be a reference to a
662tuple -- `std::tuple<int, short, long>&` in ``t1``'s case. Our primitives do
663not recognize references to tuples as type lists, so we need to strip them off.
664
665There are two problems with our return type computation though. One, what if
666`tuple_cat` is called without any arguments? We return `mp_list<>` in that
667case, but the correct result is `std::tuple<>`.
668
669Two, what if we call `tuple_cat` with a first argument that is a `std::pair`?
670We'll try to append more elements to `std::pair`, and it will fail.
671
672We can solve both our problems by using an empty tuple as the first argument to
673`mp_append`:
674```
675template<class... Tp,
676    class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
677    R tuple_cat( Tp &&... tp );
678```
679With the return type taken care of, let's now move on to computing inner. We
680have
681```
682[x1, x2, x3], [], [y1, y2, y3], [z1, z2]
683```
684as input and we need to output
685```
686[0, 0, 0, 2, 2, 2, 3, 3]
687```
688which is the concatenation of
689```
690[0, 0, 0], [], [2, 2, 2], [3, 3]
691```
692Here each tuple is the same size as the input, but is filled with a constant
693that represents its index in the argument list. The first tuple is filled with
6940, the second with 1, the third with 2, and so on.
695
696We can achieve this result if we first compute a list of indices, in our case
697`[0, 1, 2, 3]`, then use binary `mp_transform` on the two lists
698```
699[[x1, x2, x3], [], [y1, y2, y3], [z1, z2]]
700[0, 1, 2, 3]
701```
702and a function which takes a list and an integer (in the form of an
703`std::integral_constant`) and returns a list that is the same size as the
704original, but filled with the second argument.
705
706We'll call this function `mp_fill`, after `std::fill`.
707
708Functional programmers will immediately realize that `mp_fill` is
709`mp_transform` with a function that returns a constant, and here's an
710implementation along these lines:
711```
712template<class V> struct mp_constant
713{
714    template<class...> using apply = V;
715};
716
717template<class L, class V>
718    using mp_fill = mp_transform<mp_constant<V>::template apply, L>;
719```
720Here's an alternate implementation:
721```
722template<class L, class V> struct mp_fill_impl;
723
724template<template<class...> class L, class... T, class V>
725    struct mp_fill_impl<L<T...>, V>
726{
727    template<class...> using _fv = V;
728    using type = L<_fv<T>...>;
729};
730
731template<class L, class V> using mp_fill = typename mp_fill_impl<L, V>::type;
732```
733These demonstrate different styles and choosing one over the other is largely a
734matter of taste here. In the first case, we combine existing primitives; in the
735second case, we "inline" `mp_const` and even `mp_transform` in the body of
736`mp_fill_impl`.
737
738Most {cpp}11 programmers will probably find the second implementation easier to
739read.
740
741We can now `mp_fill`, but we still need the `[0, 1, 2, 3]` index sequence. We
742could write an algorithm `mp_iota` for that (named after
743http://en.cppreference.com/w/cpp/algorithm/iota[`std::iota`]), but it so
744happens that {cpp}14 already has a standard way of generating an index
745sequence, called
746http://en.cppreference.com/w/cpp/utility/integer_sequence[`std::make_index_sequence`].
747Since Eric's original solution makes use of `make_index_sequence`, let's follow
748his lead.
749
750Technically, this takes us outside of {cpp}11, but `make_index_sequence` is not
751hard to implement (if efficiency is not a concern):
752```
753template<class T, T... Ints> struct integer_sequence
754{
755};
756
757template<class S> struct next_integer_sequence;
758
759template<class T, T... Ints> struct next_integer_sequence<integer_sequence<T, Ints...>>
760{
761    using type = integer_sequence<T, Ints..., sizeof...(Ints)>;
762};
763
764template<class T, T I, T N> struct make_int_seq_impl;
765
766template<class T, T N>
767    using make_integer_sequence = typename make_int_seq_impl<T, 0, N>::type;
768
769template<class T, T I, T N> struct make_int_seq_impl
770{
771    using type = typename next_integer_sequence<
772        typename make_int_seq_impl<T, I+1, N>::type>::type;
773};
774
775template<class T, T N> struct make_int_seq_impl<T, N, N>
776{
777    using type = integer_sequence<T>;
778};
779
780template<std::size_t... Ints>
781    using index_sequence = integer_sequence<std::size_t, Ints...>;
782
783template<std::size_t N>
784    using make_index_sequence = make_integer_sequence<std::size_t, N>;
785```
786We can now obtain an `index_sequence<0, 1, 2, 3>`:
787```
788template<class... Tp,
789    class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
790    R tuple_cat( Tp &&... tp )
791{
792    std::size_t const N = sizeof...(Tp);
793
794    // inner
795
796    using seq = make_index_sequence<N>;
797}
798```
799but `make_index_sequence<4>` returns `integer_sequence<std::size_t, 0, 1, 2,
8003>`, which is not a type list. In order to work with it, we need to convert it
801to a type list, so we'll introduce a function `mp_from_sequence` that does
802that.
803```
804template<class S> struct mp_from_sequence_impl;
805
806template<template<class T, T... I> class S, class U, U... J>
807    struct mp_from_sequence_impl<S<U, J...>>
808{
809    using type = mp_list<std::integral_constant<U, J>...>;
810};
811
812template<class S> using mp_from_sequence = typename mp_from_sequence_impl<S>::type;
813```
814We can now compute the two lists that we wanted to transform with `mp_fill`:
815```
816template<class... Tp,
817    class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
818    R tuple_cat( Tp &&... tp )
819{
820    std::size_t const N = sizeof...(Tp);
821
822    // inner
823
824    using list1 = mp_list<typename std::remove_reference<Tp>::type...>;
825    using list2 = mp_from_sequence<make_index_sequence<N>>;
826
827    // list1: [[x1, x2, x3], [], [y1, y2, y3], [z1, z2]]
828    // list2: [0, 1, 2, 3]
829
830    return R{};
831}
832```
833and finish the job of computing `inner`:
834```
835template<class... Tp,
836    class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
837    R tuple_cat( Tp &&... tp )
838{
839    std::size_t const N = sizeof...(Tp);
840
841    // inner
842
843    using list1 = mp_list<typename std::remove_reference<Tp>::type...>;
844    using list2 = mp_from_sequence<make_index_sequence<N>>;
845
846    // list1: [[x1, x2, x3], [], [y1, y2, y3], [z1, z2]]
847    // list2: [0, 1, 2, 3]
848
849    using list3 = mp_transform<mp_fill, list1, list2>;
850
851    // list3: [[0, 0, 0], [], [2, 2, 2], [3, 3]]
852
853    using inner = mp_rename<list3, mp_append>; // or mp_apply<mp_append, list3>
854
855    // inner: [0, 0, 0, 2, 2, 2, 3, 3]
856
857    return R{};
858}
859```
860For `outer`, we again have
861```
862[x1, x2, x3], [], [y1, y2, y3], [z1, z2]
863```
864as input and we need to output
865```
866[0, 1, 2, 0, 1, 2, 0, 1]
867```
868which is the concatenation of
869```
870[0, 1, 2], [], [0, 1, 2], [0, 1]
871```
872The difference here is that instead of filling the tuple with a constant value,
873we need to fill it with increasing values, starting from 0, that is, with the
874result of `make_index_sequence<N>`, where `N` is the number of elements.
875
876The straightforward way to do that is to just define a metafunction `F` that
877does what we want, then use `mp_transform` to apply it to the input:
878```
879template<class N> using mp_iota = mp_from_sequence<make_index_sequence<N::value>>;
880
881template<class L> using F = mp_iota<mp_size<L>>;
882
883template<class... Tp,
884    class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
885    R tuple_cat( Tp &&... tp )
886{
887    std::size_t const N = sizeof...(Tp);
888
889    // outer
890
891    using list1 = mp_list<typename std::remove_reference<Tp>::type...>;
892    using list2 = mp_transform<F, list1>;
893
894    // list2: [[0, 1, 2], [], [0, 1, 2], [0, 1]]
895
896    using outer = mp_rename<list2, mp_append>;
897
898    // outer: [0, 1, 2, 0, 1, 2, 0, 1]
899
900    return R{};
901}
902```
903Well that was easy. Surprisingly easy. The one small annoyance is that we can't
904define `F` inside `tuple_cat` - templates can't be defined in functions.
905
906Let's put everything together.
907```
908template<class N> using mp_iota = mp_from_sequence<make_index_sequence<N::value>>;
909
910template<class L> using F = mp_iota<mp_size<L>>;
911
912template<class R, class...Is, class... Ks, class Tp>
913R tuple_cat_( mp_list<Is...>, mp_list<Ks...>, Tp tp )
914{
915    return R{ std::get<Ks::value>(std::get<Is::value>(tp))... };
916}
917
918template<class... Tp,
919    class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
920    R tuple_cat( Tp &&... tp )
921{
922    std::size_t const N = sizeof...(Tp);
923
924    // inner
925
926    using list1 = mp_list<typename std::remove_reference<Tp>::type...>;
927    using list2 = mp_from_sequence<make_index_sequence<N>>;
928
929    // list1: [[x1, x2, x3], [], [y1, y2, y3], [z1, z2]]
930    // list2: [0, 1, 2, 3]
931
932    using list3 = mp_transform<mp_fill, list1, list2>;
933
934    // list3: [[0, 0, 0], [], [2, 2, 2], [3, 3]]
935
936    using inner = mp_rename<list3, mp_append>; // or mp_apply<mp_append, list3>
937
938    // inner: [0, 0, 0, 2, 2, 2, 3, 3]
939
940    // outer
941
942    using list4 = mp_transform<F, list1>;
943
944    // list4: [[0, 1, 2], [], [0, 1, 2], [0, 1]]
945
946    using outer = mp_rename<list4, mp_append>;
947
948    // outer: [0, 1, 2, 0, 1, 2, 0, 1]
949
950    return tuple_cat_<R>( inner(), outer(),
951        std::forward_as_tuple( std::forward<Tp>(tp)... ) );
952}
953```
954This almost compiles, except that our `inner` happens to be a `std::tuple`, but
955our helper function expects an `mp_list`. (`outer` is already an `mp_list`, by
956sheer luck.) We can fix that easily enough.
957```
958return tuple_cat_<R>( mp_rename<inner, mp_list>(), outer(),
959    std::forward_as_tuple( std::forward<Tp>(tp)... ) );
960```
961Let's define a `print_tuple` function and see if everything checks out.
962```
963template<int I, int N, class... T> struct print_tuple_
964{
965    void operator()( std::tuple<T...> const & tp ) const
966    {
967        using Tp = typename std::tuple_element<I, std::tuple<T...>>::type;
968
969        print_type<Tp>( " ", ": " );
970
971        std::cout << std::get<I>( tp ) << ";";
972
973        print_tuple_< I+1, N, T... >()( tp );
974    }
975};
976
977template<int N, class... T> struct print_tuple_<N, N, T...>
978{
979    void operator()( std::tuple<T...> const & ) const
980    {
981    }
982};
983
984template<class... T> void print_tuple( std::tuple<T...> const & tp )
985{
986    std::cout << "{";
987    print_tuple_<0, sizeof...(T), T...>()( tp );
988    std::cout << " }\n";
989}
990
991int main()
992{
993    std::tuple<int, long> t1{ 1, 2 };
994    std::tuple<> t2;
995    std::tuple<float, double, long double> t3{ 3, 4, 5 };
996    std::pair<void const*, char const*> t4{ "pv", "test" };
997
998    using expected = std::tuple<int, long, float, double, long double,
999        void const*, char const*>;
1000
1001    auto result = ::tuple_cat( t1, t2, t3, t4 );
1002
1003    static_assert( std::is_same<decltype(result), expected>::value, "" );
1004
1005    print_tuple( result );
1006}
1007```
1008Output:
1009```
1010{ int: 1; long: 2; float: 3; double: 4; long double: 5; void const*: 0x407086;
1011    char const*: test; }
1012```
1013Seems to work. But there's at least one error left. To see why, replace the
1014first tuple
1015```
1016std::tuple<int, long> t1{ 1, 2 };
1017```
1018with a pair:
1019```
1020std::pair<int, long> t1{ 1, 2 };
1021```
1022We now get an error at
1023```
1024using inner = mp_rename<list3, mp_append>;
1025```
1026because the first element of `list3` is an `std::pair`, which `mp_append` tries
1027and fails to use as its return type.
1028
1029There are two ways to fix that. The first one is to apply the same trick we
1030used for the return type, and insert an empty `mp_list` at the front of
1031`list3`, which `mp_append` will use as a return type:
1032```
1033using inner = mp_rename<mp_push_front<list3, mp_list<>>, mp_append>;
1034```
1035The second way is to just convert all inputs to mp_list:
1036```
1037using list1 = mp_list<
1038    mp_rename<typename std::remove_reference<Tp>::type, mp_list>...>;
1039```
1040In both cases, inner will now be an `mp_list`, so we can omit the `mp_rename`
1041in the call to `tuple_cat_`.
1042
1043We're done. The results hopefully speak for themselves.
1044
1045## Higher order metaprogramming, or lack thereof
1046
1047Perhaps by now you're wondering why this article is called "Simple {cpp}11
1048metaprogramming", since what we covered so far wasn't particularly simple.
1049
1050The _relative_ simplicity of our approach stems from the fact that we've not
1051been doing any higher order metaprogramming, that is, we haven't introduced any
1052primitives that return metafunctions, such as `compose`, `bind`, or a lambda
1053library.
1054
1055I posit that such higher order metaprogramming is, in the majority of cases,
1056not necessary in {cpp}11. Consider, for example, Eric Niebler's solution given
1057above:
1058```
1059using outer =
1060    typelist_cat_t<
1061        typelist_transform_t<
1062            typelist<as_typelist_t<Tuples>...>,
1063            meta_compose<
1064                meta_quote<as_typelist_t>,
1065                meta_quote_i<std::size_t, make_index_sequence>,
1066                meta_quote<typelist_size_t> > > >;
1067```
1068The `meta_compose` expression takes three other ("quoted") metafunctions and
1069creates a new metafunction that applies them in order. Eric uses this example
1070as motivation to introduce the concept of a "metafunction class" and then to
1071supply various primitives that operate on metafunction classes.
1072
1073But when we have metafunctions `F`, `G` and `H`, instead of using
1074`meta_compose`, in {cpp}11 we can just do
1075```
1076template<class... T> using Fgh = F<G<H<T...>>>;
1077```
1078and that's it. The language makes defining composite functions easy, and there
1079is no need for library support. If the functions to be composed are
1080`as_typelist_t`, `std::make_index_sequence` and `typelist_size_t`, we just
1081define
1082```
1083template<class... T>
1084    using F = as_typelist_t<std::make_index_sequence<typelist_size_t<T...>::value>>;
1085```
1086Similarly, if we need a metafunction that will return `sizeof(T) < sizeof(U)`,
1087there is no need to enlist a metaprogramming lambda library as in
1088```
1089lambda<_a, _b, less<sizeof_<_a>, sizeof_<_b>>>>
1090```
1091We could just define it inline:
1092```
1093template<class T, class U> using sizeof_less = mp_bool<(sizeof(T) < sizeof(U))>;
1094```
1095
1096## One more thing
1097
1098Finally, let me show the implementations of `mp_count` and `mp_count_if`, for
1099no reason other than I find them interesting. `mp_count<L, V>` returns the
1100number of occurrences of the type `V` in the list `L`; `mp_count_if<L, P>`
1101counts the number of types in `L` for which `P<T>` is `true`.
1102
1103As a first step, I'll implement `mp_plus`. `mp_plus` is a variadic (not just
1104binary) metafunction that returns the sum of its arguments.
1105```
1106template<class... T> struct mp_plus_impl;
1107
1108template<class... T> using mp_plus = typename mp_plus_impl<T...>::type;
1109
1110template<> struct mp_plus_impl<>
1111{
1112    using type = std::integral_constant<int, 0>;
1113};
1114
1115template<class T1, class... T> struct mp_plus_impl<T1, T...>
1116{
1117    static constexpr auto _v = T1::value + mp_plus<T...>::value;
1118
1119    using type = std::integral_constant<
1120        typename std::remove_const<decltype(_v)>::type, _v>;
1121};
1122```
1123Now that we have `mp_plus`, `mp_count` is just
1124```
1125template<class L, class V> struct mp_count_impl;
1126
1127template<template<class...> class L, class... T, class V>
1128    struct mp_count_impl<L<T...>, V>
1129{
1130    using type = mp_plus<std::is_same<T, V>...>;
1131};
1132
1133template<class L, class V> using mp_count = typename mp_count_impl<L, V>::type;
1134```
1135This is another illustration of the power of parameter pack expansion. It's a
1136pity that we can't use pack expansion in `mp_plus` as well, to obtain
1137```
1138T1::value + T2::value + T3::value + T4::value + ...
1139```
1140directly. It would have been nice for `T::value + $$...$$` to have been
1141supported, and it appears that in {cpp}17, it will be.
1142
1143`mp_count_if` is similarly straightforward:
1144```
1145template<class L, template<class...> class P> struct mp_count_if_impl;
1146
1147template<template<class...> class L, class... T, template<class...> class P>
1148    struct mp_count_if_impl<L<T...>, P>
1149{
1150    using type = mp_plus<P<T>...>;
1151};
1152
1153template<class L, template<class...> class P>
1154    using mp_count_if = typename mp_count_if_impl<L, P>::type;
1155```
1156at least if we require `P` to return `bool`. If not, we'll have to coerce
1157`P<T>::value` to 0 or 1, or the count will not be correct.
1158```
1159template<bool v> using mp_bool = std::integral_constant<bool, v>;
1160
1161template<class L, template<class...> class P> struct mp_count_if_impl;
1162
1163template<template<class...> class L, class... T, template<class...> class P>
1164    struct mp_count_if_impl<L<T...>, P>
1165{
1166    using type = mp_plus<mp_bool<P<T>::value != 0>...>;
1167};
1168
1169template<class L, template<class...> class P>
1170    using mp_count_if = typename mp_count_if_impl<L, P>::type;
1171```
1172The last primitive I'll show is `mp_contains`. `mp_contains<L, V>` returns
1173whether the list `L` contains the type `V`:
1174```
1175template<class L, class V> using mp_contains = mp_bool<mp_count<L, V>::value != 0>;
1176```
1177At first sight, this implementation appears horribly naive and inefficient --
1178why would we need to count all the occurrences just to throw that away if we're
1179only interested in a boolean result -- but it's actually pretty competitive and
1180perfectly usable. We just need to add one slight optimization to `mp_plus`, the
1181engine behind `mp_count` and `mp_contains`:
1182```
1183template<class T1, class T2, class T3, class T4, class T5,
1184    class T6, class T7, class T8, class T9, class T10, class... T>
1185    struct mp_plus_impl<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>
1186{
1187    static constexpr auto _v = T1::value + T2::value + T3::value + T4::value +
1188        T5::value + T6::value + T7::value + T8::value + T9::value + T10::value +
1189        mp_plus<T...>::value;
1190
1191    using type = std::integral_constant<
1192        typename std::remove_const<decltype(_v)>::type, _v>;
1193};
1194```
1195This cuts the number of template instantiations approximately tenfold.
1196
1197## Conclusion
1198
1199I have outlined an approach to metaprogramming in {cpp}11 that
1200
1201* takes advantage of variadic templates, parameter pack expansion, and template
1202  aliases;
1203* operates on any variadic template `L<T$$...$$>`, treating it as its
1204  fundamental data structure, without mandating a specific type list
1205  representation;
1206* uses template aliases as its metafunctions, with the expression `F<T$$...$$>`
1207  serving as the equivalent of a function call;
1208* exploits the structural similarity between the data structure `L<T$$...$$>`
1209  and the metafunction call `F<T$$...$$>`;
1210* leverages parameter pack expansion as much as possible, instead of using the
1211  traditional recursive implementations;
1212* relies on inline definitions of template aliases for function composition,
1213  instead of providing library support for this task.
1214
1215## Further reading
1216
1217<<simple_cxx11_metaprogramming_2.adoc#,Part 2 is now available>>, in which I
1218show algorithms that allow us to treat type lists as sets, maps, and vectors,
1219and demonstrate various {cpp}11 implementation techniques in the process.
1220