Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / mp11 / doc / html / simple_cxx11_metaprogramming.html
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
6 <meta name="viewport" content="width=device-width, initial-scale=1.0">
7 <meta name="generator" content="Asciidoctor 1.5.8">
8 <meta name="author" content="Peter Dimov">
9 <title>Simple C&#43;&#43;11 metaprogramming</title>
10 <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
11 <style>
12 /* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
13 /* Uncomment @import statement below to use as custom stylesheet */
14 /*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
15 article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
16 audio,canvas,video{display:inline-block}
17 audio:not([controls]){display:none;height:0}
18 script{display:none!important}
19 html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
20 a{background:transparent}
21 a:focus{outline:thin dotted}
22 a:active,a:hover{outline:0}
23 h1{font-size:2em;margin:.67em 0}
24 abbr[title]{border-bottom:1px dotted}
25 b,strong{font-weight:bold}
26 dfn{font-style:italic}
27 hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
28 mark{background:#ff0;color:#000}
29 code,kbd,pre,samp{font-family:monospace;font-size:1em}
30 pre{white-space:pre-wrap}
31 q{quotes:"\201C" "\201D" "\2018" "\2019"}
32 small{font-size:80%}
33 sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
34 sup{top:-.5em}
35 sub{bottom:-.25em}
36 img{border:0}
37 svg:not(:root){overflow:hidden}
38 figure{margin:0}
39 fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
40 legend{border:0;padding:0}
41 button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
42 button,input{line-height:normal}
43 button,select{text-transform:none}
44 button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
45 button[disabled],html input[disabled]{cursor:default}
46 input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
47 button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
48 textarea{overflow:auto;vertical-align:top}
49 table{border-collapse:collapse;border-spacing:0}
50 *,*::before,*::after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
51 html,body{font-size:100%}
52 body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
53 a:hover{cursor:pointer}
54 img,object,embed{max-width:100%;height:auto}
55 object,embed{height:100%}
56 img{-ms-interpolation-mode:bicubic}
57 .left{float:left!important}
58 .right{float:right!important}
59 .text-left{text-align:left!important}
60 .text-right{text-align:right!important}
61 .text-center{text-align:center!important}
62 .text-justify{text-align:justify!important}
63 .hide{display:none}
64 img,object,svg{display:inline-block;vertical-align:middle}
65 textarea{height:auto;min-height:50px}
66 select{width:100%}
67 .center{margin-left:auto;margin-right:auto}
68 .stretch{width:100%}
69 .subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
70 div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
71 a{color:#2156a5;text-decoration:underline;line-height:inherit}
72 a:hover,a:focus{color:#1d4b8f}
73 a img{border:none}
74 p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
75 p aside{font-size:.875em;line-height:1.35;font-style:italic}
76 h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
77 h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
78 h1{font-size:2.125em}
79 h2{font-size:1.6875em}
80 h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
81 h4,h5{font-size:1.125em}
82 h6{font-size:1em}
83 hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
84 em,i{font-style:italic;line-height:inherit}
85 strong,b{font-weight:bold;line-height:inherit}
86 small{font-size:60%;line-height:inherit}
87 code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
88 ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
89 ul,ol{margin-left:1.5em}
90 ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
91 ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
92 ul.square{list-style-type:square}
93 ul.circle{list-style-type:circle}
94 ul.disc{list-style-type:disc}
95 ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
96 dl dt{margin-bottom:.3125em;font-weight:bold}
97 dl dd{margin-bottom:1.25em}
98 abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
99 abbr{text-transform:none}
100 blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
101 blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
102 blockquote cite::before{content:"\2014 \0020"}
103 blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
104 blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
105 @media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
106 h1{font-size:2.75em}
107 h2{font-size:2.3125em}
108 h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
109 h4{font-size:1.4375em}}
110 table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
111 table thead,table tfoot{background:#f7f8f7}
112 table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
113 table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
114 table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
115 table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
116 h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
117 h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
118 .clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
119 .clearfix::after,.float-group::after{clear:both}
120 *:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word}
121 *:not(pre)>code.nobreak{word-wrap:normal}
122 *:not(pre)>code.nowrap{white-space:nowrap}
123 pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
124 em em{font-style:normal}
125 strong strong{font-weight:400}
126 .keyseq{color:rgba(51,51,51,.8)}
127 kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
128 .keyseq kbd:first-child{margin-left:0}
129 .keyseq kbd:last-child{margin-right:0}
130 .menuseq,.menuref{color:#000}
131 .menuseq b:not(.caret),.menuref{font-weight:inherit}
132 .menuseq{word-spacing:-.02em}
133 .menuseq b.caret{font-size:1.25em;line-height:.8}
134 .menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
135 b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
136 b.button::before{content:"[";padding:0 3px 0 2px}
137 b.button::after{content:"]";padding:0 2px 0 3px}
138 p a>code:hover{color:rgba(0,0,0,.9)}
139 #header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
140 #header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
141 #header::after,#content::after,#footnotes::after,#footer::after{clear:both}
142 #content{margin-top:1.25em}
143 #content::before{content:none}
144 #header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
145 #header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
146 #header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
147 #header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
148 #header .details span:first-child{margin-left:-.125em}
149 #header .details span.email a{color:rgba(0,0,0,.85)}
150 #header .details br{display:none}
151 #header .details br+span::before{content:"\00a0\2013\00a0"}
152 #header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
153 #header .details br+span#revremark::before{content:"\00a0|\00a0"}
154 #header #revnumber{text-transform:capitalize}
155 #header #revnumber::after{content:"\00a0"}
156 #content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
157 #toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
158 #toc>ul{margin-left:.125em}
159 #toc ul.sectlevel0>li>a{font-style:italic}
160 #toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
161 #toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
162 #toc li{line-height:1.3334;margin-top:.3334em}
163 #toc a{text-decoration:none}
164 #toc a:active{text-decoration:underline}
165 #toctitle{color:#7a2518;font-size:1.2em}
166 @media screen and (min-width:768px){#toctitle{font-size:1.375em}
167 body.toc2{padding-left:15em;padding-right:0}
168 #toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
169 #toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
170 #toc.toc2>ul{font-size:.9em;margin-bottom:0}
171 #toc.toc2 ul ul{margin-left:0;padding-left:1em}
172 #toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
173 body.toc2.toc-right{padding-left:0;padding-right:15em}
174 body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
175 @media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
176 #toc.toc2{width:20em}
177 #toc.toc2 #toctitle{font-size:1.375em}
178 #toc.toc2>ul{font-size:.95em}
179 #toc.toc2 ul ul{padding-left:1.25em}
180 body.toc2.toc-right{padding-left:0;padding-right:20em}}
181 #content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
182 #content #toc>:first-child{margin-top:0}
183 #content #toc>:last-child{margin-bottom:0}
184 #footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
185 #footer-text{color:rgba(255,255,255,.8);line-height:1.44}
186 #content{margin-bottom:.625em}
187 .sect1{padding-bottom:.625em}
188 @media screen and (min-width:768px){#content{margin-bottom:1.25em}
189 .sect1{padding-bottom:1.25em}}
190 .sect1:last-child{padding-bottom:0}
191 .sect1+.sect1{border-top:1px solid #e7e7e9}
192 #content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
193 #content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
194 #content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
195 #content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
196 #content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
197 .audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
198 .admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
199 table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
200 .paragraph.lead>p,#preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
201 table.tableblock #preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:inherit}
202 .admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
203 .admonitionblock>table td.icon{text-align:center;width:80px}
204 .admonitionblock>table td.icon img{max-width:none}
205 .admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
206 .admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6)}
207 .admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
208 .exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
209 .exampleblock>.content>:first-child{margin-top:0}
210 .exampleblock>.content>:last-child{margin-bottom:0}
211 .sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
212 .sidebarblock>:first-child{margin-top:0}
213 .sidebarblock>:last-child{margin-bottom:0}
214 .sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
215 .exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
216 .literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
217 .sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
218 .literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;overflow-x:auto;padding:1em;font-size:.8125em}
219 @media screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
220 @media screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
221 .literalblock pre.nowrap,.literalblock pre.nowrap pre,.listingblock pre.nowrap,.listingblock pre.nowrap pre{white-space:pre;word-wrap:normal}
222 .literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
223 .listingblock pre.highlightjs{padding:0}
224 .listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
225 .listingblock pre.prettyprint{border-width:0}
226 .listingblock>.content{position:relative}
227 .listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
228 .listingblock:hover code[data-lang]::before{display:block}
229 .listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:#999}
230 .listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
231 table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
232 table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
233 table.pyhltable td.code{padding-left:.75em;padding-right:0}
234 pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #dddddf}
235 pre.pygments .lineno{display:inline-block;margin-right:.25em}
236 table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
237 .quoteblock{margin:0 1em 1.25em 1.5em;display:table}
238 .quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
239 .quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
240 .quoteblock blockquote{margin:0;padding:0;border:0}
241 .quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
242 .quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
243 .quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
244 .verseblock{margin:0 1em 1.25em}
245 .verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
246 .verseblock pre strong{font-weight:400}
247 .verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
248 .quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
249 .quoteblock .attribution br,.verseblock .attribution br{display:none}
250 .quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
251 .quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
252 .quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
253 .quoteblock.abstract{margin:0 1em 1.25em;display:block}
254 .quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
255 .quoteblock.excerpt,.quoteblock .quoteblock{margin:0 0 1.25em;padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
256 .quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
257 .quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;text-align:left;margin-right:0}
258 table.tableblock{max-width:100%;border-collapse:separate}
259 p.tableblock:last-child{margin-bottom:0}
260 td.tableblock>.content{margin-bottom:-1.25em}
261 table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
262 table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}
263 table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}
264 table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}
265 table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px}
266 table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0}
267 table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}
268 table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}
269 table.frame-all{border-width:1px}
270 table.frame-sides{border-width:0 1px}
271 table.frame-topbot,table.frame-ends{border-width:1px 0}
272 table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd){background:#f8f8f7}
273 table.stripes-none tr,table.stripes-odd tr:nth-of-type(even){background:none}
274 th.halign-left,td.halign-left{text-align:left}
275 th.halign-right,td.halign-right{text-align:right}
276 th.halign-center,td.halign-center{text-align:center}
277 th.valign-top,td.valign-top{vertical-align:top}
278 th.valign-bottom,td.valign-bottom{vertical-align:bottom}
279 th.valign-middle,td.valign-middle{vertical-align:middle}
280 table thead th,table tfoot th{font-weight:bold}
281 tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
282 tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
283 p.tableblock>code:only-child{background:none;padding:0}
284 p.tableblock{font-size:1em}
285 td>div.verse{white-space:pre}
286 ol{margin-left:1.75em}
287 ul li ol{margin-left:1.5em}
288 dl dd{margin-left:1.125em}
289 dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
290 ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
291 ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
292 ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
293 ul.unstyled,ol.unstyled{margin-left:0}
294 ul.checklist{margin-left:.625em}
295 ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
296 ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em}
297 ul.inline{display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
298 ul.inline>li{margin-left:1.25em}
299 .unstyled dl dt{font-weight:400;font-style:normal}
300 ol.arabic{list-style-type:decimal}
301 ol.decimal{list-style-type:decimal-leading-zero}
302 ol.loweralpha{list-style-type:lower-alpha}
303 ol.upperalpha{list-style-type:upper-alpha}
304 ol.lowerroman{list-style-type:lower-roman}
305 ol.upperroman{list-style-type:upper-roman}
306 ol.lowergreek{list-style-type:lower-greek}
307 .hdlist>table,.colist>table{border:0;background:none}
308 .hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
309 td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
310 td.hdlist1{font-weight:bold;padding-bottom:1.25em}
311 .literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
312 .colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
313 .colist td:not([class]):first-child img{max-width:none}
314 .colist td:not([class]):last-child{padding:.25em 0}
315 .thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
316 .imageblock.left{margin:.25em .625em 1.25em 0}
317 .imageblock.right{margin:.25em 0 1.25em .625em}
318 .imageblock>.title{margin-bottom:0}
319 .imageblock.thumb,.imageblock.th{border-width:6px}
320 .imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
321 .image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
322 .image.left{margin-right:.625em}
323 .image.right{margin-left:.625em}
324 a.image{text-decoration:none;display:inline-block}
325 a.image object{pointer-events:none}
326 sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
327 sup.footnote a,sup.footnoteref a{text-decoration:none}
328 sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
329 #footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
330 #footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
331 #footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
332 #footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
333 #footnotes .footnote:last-of-type{margin-bottom:0}
334 #content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
335 .gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
336 .gist .file-data>table td.line-data{width:99%}
337 div.unbreakable{page-break-inside:avoid}
338 .big{font-size:larger}
339 .small{font-size:smaller}
340 .underline{text-decoration:underline}
341 .overline{text-decoration:overline}
342 .line-through{text-decoration:line-through}
343 .aqua{color:#00bfbf}
344 .aqua-background{background-color:#00fafa}
345 .black{color:#000}
346 .black-background{background-color:#000}
347 .blue{color:#0000bf}
348 .blue-background{background-color:#0000fa}
349 .fuchsia{color:#bf00bf}
350 .fuchsia-background{background-color:#fa00fa}
351 .gray{color:#606060}
352 .gray-background{background-color:#7d7d7d}
353 .green{color:#006000}
354 .green-background{background-color:#007d00}
355 .lime{color:#00bf00}
356 .lime-background{background-color:#00fa00}
357 .maroon{color:#600000}
358 .maroon-background{background-color:#7d0000}
359 .navy{color:#000060}
360 .navy-background{background-color:#00007d}
361 .olive{color:#606000}
362 .olive-background{background-color:#7d7d00}
363 .purple{color:#600060}
364 .purple-background{background-color:#7d007d}
365 .red{color:#bf0000}
366 .red-background{background-color:#fa0000}
367 .silver{color:#909090}
368 .silver-background{background-color:#bcbcbc}
369 .teal{color:#006060}
370 .teal-background{background-color:#007d7d}
371 .white{color:#bfbfbf}
372 .white-background{background-color:#fafafa}
373 .yellow{color:#bfbf00}
374 .yellow-background{background-color:#fafa00}
375 span.icon>.fa{cursor:default}
376 a span.icon>.fa{cursor:inherit}
377 .admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
378 .admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
379 .admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
380 .admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
381 .admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
382 .admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
383 .conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
384 .conum[data-value] *{color:#fff!important}
385 .conum[data-value]+b{display:none}
386 .conum[data-value]::after{content:attr(data-value)}
387 pre .conum[data-value]{position:relative;top:-.125em}
388 b.conum *{color:inherit!important}
389 .conum:not([data-value]):empty{display:none}
390 dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
391 h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
392 p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
393 p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
394 p{margin-bottom:1.25rem}
395 .sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
396 .exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
397 .print-only{display:none!important}
398 @page{margin:1.25cm .75cm}
399 @media print{*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
400 html{font-size:80%}
401 a{color:inherit!important;text-decoration:underline!important}
402 a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
403 a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
404 abbr[title]::after{content:" (" attr(title) ")"}
405 pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
406 thead{display:table-header-group}
407 svg{max-width:100%}
408 p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
409 h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
410 #toc,.sidebarblock,.exampleblock>.content{background:none!important}
411 #toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
412 body.book #header{text-align:center}
413 body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
414 body.book #header .details{border:0!important;display:block;padding:0!important}
415 body.book #header .details span:first-child{margin-left:0!important}
416 body.book #header .details br{display:block}
417 body.book #header .details br+span::before{content:none!important}
418 body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
419 body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
420 .listingblock code[data-lang]::before{display:block}
421 #footer{padding:0 .9375em}
422 .hide-on-print{display:none!important}
423 .print-only{display:block!important}
424 .hide-for-print{display:none!important}
425 .show-for-print{display:inherit!important}}
426 @media print,amzn-kf8{#header>h1:first-child{margin-top:1.25rem}
427 .sect1{padding:0!important}
428 .sect1+.sect1{border:0}
429 #footer{background:none}
430 #footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
431 @media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
432 </style>
433 </head>
434 <body class="article toc2 toc-left">
435 <div id="header">
436 <h1>Simple C&#43;&#43;11 metaprogramming</h1>
437 <div class="details">
438 <span id="author" class="author">Peter Dimov</span><br>
439 <span id="revdate">2015-05-26</span>
440 </div>
441 <div id="toc" class="toc2">
442 <div id="toctitle">Table of Contents</div>
443 <ul class="sectlevel1">
444 <li><a href="#c11_changes_the_playing_field">C&#43;&#43;11 changes the playing field</a></li>
445 <li><a href="#type_lists_and_mp_rename">Type lists and mp_rename</a></li>
446 <li><a href="#mp_transform">mp_transform</a></li>
447 <li><a href="#mp_transform_part_two">mp_transform, part two</a></li>
448 <li><a href="#the_infamous_tuple_cat_challenge">The infamous tuple_cat challenge</a></li>
449 <li><a href="#higher_order_metaprogramming_or_lack_thereof">Higher order metaprogramming, or lack thereof</a></li>
450 <li><a href="#one_more_thing">One more thing</a></li>
451 <li><a href="#conclusion">Conclusion</a></li>
452 <li><a href="#further_reading">Further reading</a></li>
453 </ul>
454 </div>
455 </div>
456 <div id="content">
457 <div id="preamble">
458 <div class="sectionbody">
459 <div class="paragraph lead">
460 <p><em>With variadic templates, parameter packs and template aliases</em></p>
461 </div>
462 <div class="admonitionblock note">
463 <table>
464 <tr>
465 <td class="icon">
466 <div class="title">Note</div>
467 </td>
468 <td class="content">
469 I was motivated to write this after I read Eric Niebler&#8217;s
470 thought-provoking
471 <a href="http://ericniebler.com/2014/11/13/tiny-metaprogramming-library/">Tiny
472 Metaprogramming Library</a> article. Thanks Eric.
473 </td>
474 </tr>
475 </table>
476 </div>
477 </div>
478 </div>
479 <div class="sect1">
480 <h2 id="c11_changes_the_playing_field">C&#43;&#43;11 changes the playing field</h2>
481 <div class="sectionbody">
482 <div class="paragraph">
483 <p>The wide acceptance of <a href="http://www.boost.org/libs/mpl">Boost.MPL</a> made C&#43;&#43;
484 metaprogramming seem a solved problem. Perhaps MPL wasn&#8217;t ideal, but it was
485 good enough to the point that there wasn&#8217;t really a need to seek or produce
486 alternatives.</p>
487 </div>
488 <div class="paragraph">
489 <p>C&#43;&#43;11 changed the playing field. The addition of variadic templates with
490 their associated parameter packs added a compile-time list of types structure
491 directly into the language. Whereas before every metaprogramming library
492 defined its own type list, and MPL defined several, in C&#43;&#43;11, type lists are
493 as easy as</p>
494 </div>
495 <div class="listingblock">
496 <div class="content">
497 <pre class="highlight"><code>// C++11
498 template&lt;class... T&gt; struct type_list {};</code></pre>
499 </div>
500 </div>
501 <div class="paragraph">
502 <p>and there is hardly a reason to use anything else.</p>
503 </div>
504 <div class="paragraph">
505 <p>Template aliases are another game changer. Previously, "metafunctions", that
506 is, templates that took one type and produced another, looked like</p>
507 </div>
508 <div class="listingblock">
509 <div class="content">
510 <pre class="highlight"><code>// C++03
511 template&lt;class T&gt; struct add_pointer { typedef T* type; };</code></pre>
512 </div>
513 </div>
514 <div class="paragraph">
515 <p>and were used in the following manner:</p>
516 </div>
517 <div class="listingblock">
518 <div class="content">
519 <pre class="highlight"><code>// C++03
520 typedef typename add_pointer&lt;X&gt;::type Xp;</code></pre>
521 </div>
522 </div>
523 <div class="paragraph">
524 <p>In C&#43;&#43;11, metafunctions can be template aliases, instead of class templates:</p>
525 </div>
526 <div class="listingblock">
527 <div class="content">
528 <pre class="highlight"><code>// C++11
529 template&lt;class T&gt; using add_pointer = T*;</code></pre>
530 </div>
531 </div>
532 <div class="paragraph">
533 <p>The above example use then becomes</p>
534 </div>
535 <div class="listingblock">
536 <div class="content">
537 <pre class="highlight"><code>// C++11
538 typedef add_pointer&lt;X&gt; Xp;</code></pre>
539 </div>
540 </div>
541 <div class="paragraph">
542 <p>or, if you prefer to be seen as C&#43;&#43;11-savvy,</p>
543 </div>
544 <div class="listingblock">
545 <div class="content">
546 <pre class="highlight"><code>// C++11
547 using Xp = add_pointer&lt;X&gt;;</code></pre>
548 </div>
549 </div>
550 <div class="paragraph">
551 <p>This is a considerable improvement in more complex expressions:</p>
552 </div>
553 <div class="listingblock">
554 <div class="content">
555 <pre class="highlight"><code>// C++03
556 typedef
557     typename add_reference&lt;
558         typename add_const&lt;
559             typename add_pointer&lt;X&gt;::type
560         &gt;::type
561     &gt;::type Xpcr;</code></pre>
562 </div>
563 </div>
564 <div class="listingblock">
565 <div class="content">
566 <pre class="highlight"><code>// C++11
567 using Xpcr = add_reference&lt;add_const&lt;add_pointer&lt;X&gt;&gt;&gt;;</code></pre>
568 </div>
569 </div>
570 <div class="paragraph">
571 <p>(The example also takes advantage of another C&#43;&#43;11 feature - you can now use
572 <code>&gt;&gt;</code> to close templates without it being interpreted as a right shift.)</p>
573 </div>
574 <div class="paragraph">
575 <p>In addition, template aliases can be passed to template template parameters:</p>
576 </div>
577 <div class="listingblock">
578 <div class="content">
579 <pre class="highlight"><code>// C++11
580 template&lt;template&lt;class... T&gt; class F&gt; struct X
581 {
582 };
583
584 X&lt;add_pointer&gt;; // works!</code></pre>
585 </div>
586 </div>
587 <div class="paragraph">
588 <p>These language improvements allow for C&#43;&#43;11 metaprogramming that is
589 substantially different than its idiomatic C&#43;&#43;03 equivalent. Boost.MPL is no
590 longer good enough, and <em>something must be done</em>. But what?</p>
591 </div>
592 </div>
593 </div>
594 <div class="sect1">
595 <h2 id="type_lists_and_mp_rename">Type lists and mp_rename</h2>
596 <div class="sectionbody">
597 <div class="paragraph">
598 <p>Let&#8217;s start with the basics. Our basic data structure will be the type list:</p>
599 </div>
600 <div class="listingblock">
601 <div class="content">
602 <pre class="highlight"><code>template&lt;class... T&gt; struct mp_list {};</code></pre>
603 </div>
604 </div>
605 <div class="paragraph">
606 <p>Why the <code>mp_</code> prefix? mp obviously stands for metaprogramming, but could we not
607 have used a namespace?</p>
608 </div>
609 <div class="paragraph">
610 <p>Indeed we could have. Past experience with Boost.MPL however indicates that
611 name conflicts between our metaprogramming primitives and standard identifiers
612 (such as <code>list</code>) and keywords (such as <code>if</code>, <code>int</code> or <code>true</code>) will be common
613 and will be a source of problems. With a prefix, we avoid all that trouble.</p>
614 </div>
615 <div class="paragraph">
616 <p>So we have our type list and can put things into it:</p>
617 </div>
618 <div class="listingblock">
619 <div class="content">
620 <pre class="highlight"><code>using list = mp_list&lt;int, char, float, double, void&gt;;</code></pre>
621 </div>
622 </div>
623 <div class="paragraph">
624 <p>but can&#8217;t do anything else with it yet. We&#8217;ll need a library of primitives that
625 operate on <code>mp_list</code>s. But before we get into that, let&#8217;s consider another
626 interesting question first.</p>
627 </div>
628 <div class="paragraph">
629 <p>Suppose we have our library of primitives that can do things with a <code>mp_list</code>,
630 but some other code hands us a type list that is not an <code>mp_list</code>, such as for
631 example an <code>std::tuple&lt;int, float, void*&gt;</code>, or
632 <code><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4115.html">std::packer</a>&lt;int,
633 float, void*&gt;</code>.</p>
634 </div>
635 <div class="paragraph">
636 <p>Suppose we need to modify this external list of types in some manner (change
637 the types into pointers, perhaps) and give back the transformed result in the
638 form it was given to us, <code>std::tuple&lt;int*, float*, void**&gt;</code> in the first
639 case and <code>std::packer&lt;int*, float*, void**&gt;</code> in the second.</p>
640 </div>
641 <div class="paragraph">
642 <p>To do that, we need to first convert <code>std::tuple&lt;int, float, void*&gt;</code> to
643 <code>mp_list&lt;int, float, void*&gt;</code>, apply <code>add_pointer</code> to each element obtaining
644 <code>mp_list&lt;int*, float*, void**&gt;</code>, then convert that back to <code>std::tuple</code>.</p>
645 </div>
646 <div class="paragraph">
647 <p>These conversion steps are a quite common occurrence, and we&#8217;ll write a
648 primitive that helps us perform them, called <code>mp_rename</code>. We want</p>
649 </div>
650 <div class="listingblock">
651 <div class="content">
652 <pre class="highlight"><code>mp_rename&lt;std::tuple&lt;int, float, void*&gt;, mp_list&gt;</code></pre>
653 </div>
654 </div>
655 <div class="paragraph">
656 <p>to give us</p>
657 </div>
658 <div class="listingblock">
659 <div class="content">
660 <pre class="highlight"><code>mp_list&lt;int, float, void*&gt;</code></pre>
661 </div>
662 </div>
663 <div class="paragraph">
664 <p>and conversely,</p>
665 </div>
666 <div class="listingblock">
667 <div class="content">
668 <pre class="highlight"><code>mp_rename&lt;mp_list&lt;int, float, void*&gt;, std::tuple&gt;</code></pre>
669 </div>
670 </div>
671 <div class="paragraph">
672 <p>to give us</p>
673 </div>
674 <div class="listingblock">
675 <div class="content">
676 <pre class="highlight"><code>std::tuple&lt;int, float, void*&gt;</code></pre>
677 </div>
678 </div>
679 <div class="paragraph">
680 <p>Here is the implementation of <code>mp_rename</code>:</p>
681 </div>
682 <div class="listingblock">
683 <div class="content">
684 <pre class="highlight"><code>template&lt;class A, template&lt;class...&gt; class B&gt; struct mp_rename_impl;
685
686 template&lt;template&lt;class...&gt; class A, class... T, template&lt;class...&gt; class B&gt;
687     struct mp_rename_impl&lt;A&lt;T...&gt;, B&gt;
688 {
689     using type = B&lt;T...&gt;;
690 };
691
692 template&lt;class A, template&lt;class...&gt; class B&gt;
693     using mp_rename = typename mp_rename_impl&lt;A, B&gt;::type;</code></pre>
694 </div>
695 </div>
696 <div class="paragraph">
697 <p>(This pattern of a template alias forwarding to a class template doing the
698 actual work is common; class templates can be specialized, whereas template
699 aliases cannot.)</p>
700 </div>
701 <div class="paragraph">
702 <p>Note that <code>mp_rename</code> does not treat any list type as special, not even
703 <code>mp_list</code>; it can rename any variadic class template into any other. You could
704 use it to rename <code>std::packer</code> to <code>std::tuple</code> to <code>std::variant</code> (once there is
705 such a thing) and it will happily oblige.</p>
706 </div>
707 <div class="paragraph">
708 <p>In fact, it can even rename non-variadic class templates, as in the following
709 examples:</p>
710 </div>
711 <div class="listingblock">
712 <div class="content">
713 <pre class="highlight"><code>mp_rename&lt;std::pair&lt;int, float&gt;, std::tuple&gt;        // -&gt; std::tuple&lt;int, float&gt;
714 mp_rename&lt;mp_list&lt;int, float&gt;, std::pair&gt;           // -&gt; std::pair&lt;int, float&gt;
715 mp_rename&lt;std::shared_ptr&lt;int&gt;, std::unique_ptr&gt;    // -&gt; std::unique_ptr&lt;int&gt;</code></pre>
716 </div>
717 </div>
718 <div class="paragraph">
719 <p>There is a limit to the magic; <code>unique_ptr</code> can&#8217;t be renamed to <code>shared_ptr</code>:</p>
720 </div>
721 <div class="listingblock">
722 <div class="content">
723 <pre class="highlight"><code>mp_rename&lt;std::unique_ptr&lt;int&gt;, std::shared_ptr&gt;    // error</code></pre>
724 </div>
725 </div>
726 <div class="paragraph">
727 <p>because <code>unique_ptr&lt;int&gt;</code> is actually <code>unique_ptr&lt;int,
728 std::default_delete&lt;int&gt;&gt;</code> and <code>mp_rename</code> renames it to <code>shared_ptr&lt;int,
729 std::default_delete&lt;int&gt;&gt;</code>, which doesn&#8217;t compile. But it still works in many
730 more cases than one would naively expect at first.</p>
731 </div>
732 <div class="paragraph">
733 <p>With conversions no longer a problem, let&#8217;s move on to primitives and define a
734 simple one, <code>mp_size</code>, for practice. We want <code>mp_size&lt;mp_list&lt;T...&gt;&gt;</code> to
735 give us the number of elements in the list, that is, the value of the
736 expression <code>sizeof...(T)</code>.</p>
737 </div>
738 <div class="listingblock">
739 <div class="content">
740 <pre class="highlight"><code>template&lt;class L&gt; struct mp_size_impl;
741
742 template&lt;class... T&gt; struct mp_size_impl&lt;mp_list&lt;T...&gt;&gt;
743 {
744     using type = std::integral_constant&lt;std::size_t, sizeof...(T)&gt;;
745 };
746
747 template&lt;class L&gt; using mp_size = typename mp_size_impl&lt;L&gt;::type;</code></pre>
748 </div>
749 </div>
750 <div class="paragraph">
751 <p>This is relatively straightforward, except for the <code>std::integral_constant</code>.
752 What is it and why do we need it?</p>
753 </div>
754 <div class="paragraph">
755 <p><code>std::integral_constant</code> is a standard C&#43;&#43;11 type that wraps an integral
756 constant (that is, a compile-time constant integer value) into a type.</p>
757 </div>
758 <div class="paragraph">
759 <p>Since metaprogramming operates on type lists, which can only hold types, it&#8217;s
760 convenient to represent compile-time constants as types. This allows us to
761 treat lists of types and lists of values in a uniform manner. It is therefore
762 idiomatic in metaprogramming to take and return types instead of values, and
763 this is what we have done. If at some later point we want the actual value, we
764 can use the expression <code>mp_size&lt;L&gt;::value</code> to retrieve it.</p>
765 </div>
766 <div class="paragraph">
767 <p>We now have our <code>mp_size</code>, but you may have noticed that there&#8217;s an interesting
768 difference between <code>mp_size</code> and <code>mp_rename</code>. Whereas I made a point of
769 <code>mp_rename</code> not treating <code>mp_list</code> as a special case, <code>mp_size</code> very much does:</p>
770 </div>
771 <div class="listingblock">
772 <div class="content">
773 <pre class="highlight"><code>template&lt;class... T&gt; struct mp_size_impl&lt;mp_list&lt;T...&gt;&gt;</code></pre>
774 </div>
775 </div>
776 <div class="paragraph">
777 <p>Is this really necessary? Can we not use the same technique in the
778 implementation of <code>mp_size</code> as we did in <code>mp_rename</code>?</p>
779 </div>
780 <div class="listingblock">
781 <div class="content">
782 <pre class="highlight"><code>template&lt;class L&gt; struct mp_size_impl;
783
784 template&lt;template&lt;class...&gt; class L, class... T&gt; struct mp_size_impl&lt;L&lt;T...&gt;&gt;
785 {
786     using type = std::integral_constant&lt;std::size_t, sizeof...(T)&gt;;
787 };
788
789 template&lt;class L&gt; using mp_size = typename mp_size_impl&lt;L&gt;::type;</code></pre>
790 </div>
791 </div>
792 <div class="paragraph">
793 <p>Yes, we very much can, and this improvement allows us to use <code>mp_size</code> on any
794 other type lists, such as <code>std::tuple</code>. It turns <code>mp_size</code> into a truly generic
795 primitive.</p>
796 </div>
797 <div class="paragraph">
798 <p>This is nice. It is so nice that I&#8217;d argue that all our metaprogramming
799 primitives ought to have this property. If someone hands us a type list in the
800 form of an <code>std::tuple</code>, we should be able to operate on it directly, avoiding
801 the conversions to and from <code>mp_list</code>.</p>
802 </div>
803 <div class="paragraph">
804 <p>So do we no longer have any need for <code>mp_rename</code>? Not quite. Apart from the
805 fact that sometimes we really do need to rename type lists, there is another
806 surprising task for which <code>mp_rename</code> is useful.</p>
807 </div>
808 <div class="paragraph">
809 <p>To illustrate it, let me introduce the primitive <code>mp_length</code>. It&#8217;s similar to
810 <code>mp_size</code>, but while <code>mp_size</code> takes a type list as an argument, <code>mp_length</code>
811 takes a variadic parameter pack and returns its length; or, stated differently,
812 it returns its number of arguments:</p>
813 </div>
814 <div class="listingblock">
815 <div class="content">
816 <pre class="highlight"><code>template&lt;class... T&gt; using mp_length =
817     std::integral_constant&lt;std::size_t, sizeof...(T)&gt;;</code></pre>
818 </div>
819 </div>
820 <div class="paragraph">
821 <p>How would we implement <code>mp_size</code> in terms of <code>mp_length</code>? One option is to just
822 substitute the implementation of the latter into the former:</p>
823 </div>
824 <div class="listingblock">
825 <div class="content">
826 <pre class="highlight"><code>template&lt;template&lt;class...&gt; class L, class... T&gt; struct mp_size_impl&lt;L&lt;T...&gt;&gt;
827 {
828     using type = mp_length&lt;T...&gt;;
829 };</code></pre>
830 </div>
831 </div>
832 <div class="paragraph">
833 <p>but there is another way, much less mundane. Think about what <code>mp_size</code> does.
834 It takes the argument</p>
835 </div>
836 <div class="listingblock">
837 <div class="content">
838 <pre class="highlight"><code><strong>mp_list</strong>&lt;int, void, float&gt;</code></pre>
839 </div>
840 </div>
841 <div class="paragraph">
842 <p>and returns</p>
843 </div>
844 <div class="listingblock">
845 <div class="content">
846 <pre class="highlight"><code><strong>mp_length</strong>&lt;int, void, float&gt;</code></pre>
847 </div>
848 </div>
849 <div class="paragraph">
850 <p>Do we already have a primitive that does a similar thing?</p>
851 </div>
852 <div class="paragraph">
853 <p>(Not much of a choice, is there?)</p>
854 </div>
855 <div class="paragraph">
856 <p>Indeed we have, and it&#8217;s called <code>mp_rename</code>.</p>
857 </div>
858 <div class="listingblock">
859 <div class="content">
860 <pre class="highlight"><code>template&lt;class L&gt; using mp_size = mp_rename&lt;L, mp_length&gt;;</code></pre>
861 </div>
862 </div>
863 <div class="paragraph">
864 <p>I don&#8217;t know about you, but I find this technique fascinating. It exploits the
865 structural similarity between a list, <code>L&lt;T...&gt;</code>, and a metafunction "call",
866 <code>F&lt;T...&gt;</code>, and the fact that the language sees the things the same way and
867 allows us to pass the template alias <code>mp_length</code> to <code>mp_rename</code> as if it were
868 an ordinary class template such as <code>mp_list</code>.</p>
869 </div>
870 <div class="paragraph">
871 <p>(Other metaprogramming libraries provide a dedicated <code>apply</code> primitive for
872 this job. <code>apply&lt;F, L&gt;</code> calls the metafunction <code>F</code> with the contents of the
873 list <code>L</code>. We&#8217;ll add an alias <code>mp_apply&lt;F, L&gt;</code> that calls <code>mp_rename&lt;L, F&gt;</code> for
874 readability.)</p>
875 </div>
876 <div class="listingblock">
877 <div class="content">
878 <pre class="highlight"><code>template&lt;template&lt;class...&gt; class F, class L&gt; using mp_apply = mp_rename&lt;L, F&gt;;</code></pre>
879 </div>
880 </div>
881 </div>
882 </div>
883 <div class="sect1">
884 <h2 id="mp_transform">mp_transform</h2>
885 <div class="sectionbody">
886 <div class="paragraph">
887 <p>Let&#8217;s revisit the example I gave earlier - someone hands us <code>std::tuple&lt;X, Y,
888 Z&gt;</code> and we need to compute <code>std::tuple&lt;X*, Y*, Z*&gt;</code>. We already have
889 <code>add_pointer</code>:</p>
890 </div>
891 <div class="listingblock">
892 <div class="content">
893 <pre class="highlight"><code>template&lt;class T&gt; using add_pointer = T*;</code></pre>
894 </div>
895 </div>
896 <div class="paragraph">
897 <p>so we just need to apply it to each element of the input tuple.</p>
898 </div>
899 <div class="paragraph">
900 <p>The algorithm that takes a function and a list and applies the function to each
901 element is called <code>transform</code> in Boost.MPL and the STL and <code>map</code> in functional
902 languages. We&#8217;ll use <code>transform</code>, for consistency with the established C&#43;&#43;
903 practice (<code>map</code> is a data structure in both the STL and Boost.MPL.)</p>
904 </div>
905 <div class="paragraph">
906 <p>We&#8217;ll call our algorithm <code>mp_transform</code>, and <code>mp_transform&lt;F, L&gt;</code> will apply
907 <code>F</code> to each element of <code>L</code> and return the result. Usually, the argument order
908 is reversed and the function comes last. Our reasons to put it at the front
909 will become evident later.</p>
910 </div>
911 <div class="paragraph">
912 <p>There are many ways to implement <code>mp_transform</code>; the one we&#8217;ll pick will make
913 use of another primitive, <code>mp_push_front</code>. <code>mp_push_front&lt;L, T&gt;</code>, as its name
914 implies, adds <code>T</code> as a first element in <code>L</code>:</p>
915 </div>
916 <div class="listingblock">
917 <div class="content">
918 <pre class="highlight"><code>template&lt;class L, class T&gt; struct mp_push_front_impl;
919
920 template&lt;template&lt;class...&gt; class L, class... U, class T&gt;
921     struct mp_push_front_impl&lt;L&lt;U...&gt;, T&gt;
922 {
923     using type = L&lt;T, U...&gt;;
924 };
925
926 template&lt;class L, class T&gt;
927     using mp_push_front = typename mp_push_front_impl&lt;L, T&gt;::type;</code></pre>
928 </div>
929 </div>
930 <div class="paragraph">
931 <p>There is no reason to constrain <code>mp_push_front</code> to a single element though. In
932 C&#43;&#43;11, variadic templates should be our default choice, and the
933 implementation of <code>mp_push_front</code> that can take an arbitrary number of elements
934 is almost identical:</p>
935 </div>
936 <div class="listingblock">
937 <div class="content">
938 <pre class="highlight"><code>template&lt;class L, class... T&gt; struct mp_push_front_impl;
939
940 template&lt;template&lt;class...&gt; class L, class... U, class... T&gt;
941     struct mp_push_front_impl&lt;L&lt;U...&gt;, T...&gt;
942 {
943     using type = L&lt;T..., U...&gt;;
944 };
945
946 template&lt;class L, class... T&gt;
947     using mp_push_front = typename mp_push_front_impl&lt;L, T...&gt;::type;</code></pre>
948 </div>
949 </div>
950 <div class="paragraph">
951 <p>On to <code>mp_transform</code>:</p>
952 </div>
953 <div class="listingblock">
954 <div class="content">
955 <pre class="highlight"><code>template&lt;template&lt;class...&gt; class F, class L&gt; struct mp_transform_impl;
956
957 template&lt;template&lt;class...&gt; class F, class L&gt;
958     using mp_transform = typename mp_transform_impl&lt;F, L&gt;::type;
959
960 template&lt;template&lt;class...&gt; class F, template&lt;class...&gt; class L&gt;
961     struct mp_transform_impl&lt;F, L&lt;&gt;&gt;
962 {
963     using type = L&lt;&gt;;
964 };
965
966 template&lt;template&lt;class...&gt; class F, template&lt;class...&gt; class L, class T1, class... T&gt;
967     struct mp_transform_impl&lt;F, L&lt;T1, T...&gt;&gt;
968 {
969     using _first = F&lt;T1&gt;;
970     using _rest = mp_transform&lt;F, L&lt;T...&gt;&gt;;
971
972     using type = mp_push_front&lt;_rest, _first&gt;;
973 };</code></pre>
974 </div>
975 </div>
976 <div class="paragraph">
977 <p>This is a straightforward recursive implementation that should be familiar to
978 people with functional programming background.</p>
979 </div>
980 <div class="paragraph">
981 <p>Can we do better? It turns out that in C&#43;&#43;11, we can.</p>
982 </div>
983 <div class="listingblock">
984 <div class="content">
985 <pre class="highlight"><code>template&lt;template&lt;class...&gt; class F, class L&gt; struct mp_transform_impl;
986
987 template&lt;template&lt;class...&gt; class F, class L&gt;
988     using mp_transform = typename mp_transform_impl&lt;F, L&gt;::type;
989
990 template&lt;template&lt;class...&gt; class F, template&lt;class...&gt; class L, class... T&gt;
991     struct mp_transform_impl&lt;F, L&lt;T...&gt;&gt;
992 {
993     using type = L&lt;F&lt;T&gt;...&gt;;
994 };</code></pre>
995 </div>
996 </div>
997 <div class="paragraph">
998 <p>Here we take advantage of the fact that pack expansion is built into the
999 language, so the <code>F&lt;T&gt;...</code> part does all the iteration work for us.</p>
1000 </div>
1001 <div class="paragraph">
1002 <p>We can now solve our original challenge: given an <code>std::tuple</code> of types, return
1003 an <code>std::tuple</code> of pointers to these types:</p>
1004 </div>
1005 <div class="listingblock">
1006 <div class="content">
1007 <pre class="highlight"><code>using input = std::tuple&lt;int, void, float&gt;;
1008 using expected = std::tuple&lt;int*, void*, float*&gt;;
1009
1010 using result = mp_transform&lt;add_pointer, input&gt;;
1011
1012 static_assert( std::is_same&lt;result, expected&gt;::value, "" );</code></pre>
1013 </div>
1014 </div>
1015 </div>
1016 </div>
1017 <div class="sect1">
1018 <h2 id="mp_transform_part_two">mp_transform, part two</h2>
1019 <div class="sectionbody">
1020 <div class="paragraph">
1021 <p>What if we had a pair of tuples as input, and had to produce the corresponding
1022 tuple of pairs? For example, given</p>
1023 </div>
1024 <div class="listingblock">
1025 <div class="content">
1026 <pre class="highlight"><code>using input = std::pair&lt;std::tuple&lt;X1, X2, X3&gt;, std::tuple&lt;Y1, Y2, Y3&gt;&gt;;</code></pre>
1027 </div>
1028 </div>
1029 <div class="paragraph">
1030 <p>we had to produce</p>
1031 </div>
1032 <div class="listingblock">
1033 <div class="content">
1034 <pre class="highlight"><code>using expected = std::tuple&lt;std::pair&lt;X1, Y1&gt;, std::pair&lt;X2, Y2&gt;, std::pair&lt;X3, Y3&gt;&gt;;</code></pre>
1035 </div>
1036 </div>
1037 <div class="paragraph">
1038 <p>We need to take the two lists, represented by tuples in the input, and combine
1039 them pairwise by using <code>std::pair</code>. If we think of <code>std::pair</code> as a function
1040 <code>F</code>, this task appears very similar to <code>mp_transform</code>, except we need to use a
1041 binary function and two lists.</p>
1042 </div>
1043 <div class="paragraph">
1044 <p>Changing our unary transform algorithm into a binary one isn&#8217;t hard:</p>
1045 </div>
1046 <div class="listingblock">
1047 <div class="content">
1048 <pre class="highlight"><code>template&lt;template&lt;class...&gt; class F, class L1, class L2&gt;
1049     struct mp_transform2_impl;
1050
1051 template&lt;template&lt;class...&gt; class F, class L1, class L2&gt;
1052     using mp_transform2 = typename mp_transform2_impl&lt;F, L1, L2&gt;::type;
1053
1054 template&lt;template&lt;class...&gt; class F,
1055     template&lt;class...&gt; class L1, class... T1,
1056     template&lt;class...&gt; class L2, class... T2&gt;
1057     struct mp_transform2_impl&lt;F, L1&lt;T1...&gt;, L2&lt;T2...&gt;&gt;
1058 {
1059     static_assert( sizeof...(T1) == sizeof...(T2),
1060         "The arguments of mp_transform2 should be of the same size" );
1061
1062     using type = L1&lt;F&lt;T1,T2&gt;...&gt;;
1063 };</code></pre>
1064 </div>
1065 </div>
1066 <div class="paragraph">
1067 <p>and we can now do</p>
1068 </div>
1069 <div class="listingblock">
1070 <div class="content">
1071 <pre class="highlight"><code>using input = std::pair&lt;std::tuple&lt;X1, X2, X3&gt;, std::tuple&lt;Y1, Y2, Y3&gt;&gt;;
1072 using expected = std::tuple&lt;std::pair&lt;X1, Y1&gt;, std::pair&lt;X2, Y2&gt;, std::pair&lt;X3, Y3&gt;&gt;;
1073
1074 using result = mp_transform2&lt;std::pair, input::first_type, input::second_type&gt;;
1075
1076 static_assert( std::is_same&lt;result, expected&gt;::value, "" );</code></pre>
1077 </div>
1078 </div>
1079 <div class="paragraph">
1080 <p>again exploiting the similarity between metafunctions and ordinary class
1081 templates such as <code>std::pair</code>, this time in the other direction; we pass
1082 <code>std::pair</code> where <code>mp_transform2</code> expects a metafunction.</p>
1083 </div>
1084 <div class="paragraph">
1085 <p>Do we <em>have</em> to use separate transform algorithms for each arity though? If we
1086 need a transform algorithm that takes a ternary function and three lists,
1087 should we name it <code>mp_transform3</code>? No, this is exactly why we put the function
1088 first. We just have to change <code>mp_transform</code> to be variadic:</p>
1089 </div>
1090 <div class="listingblock">
1091 <div class="content">
1092 <pre class="highlight"><code>template&lt;template&lt;class...&gt; class F, class... L&gt; struct mp_transform_impl;
1093
1094 template&lt;template&lt;class...&gt; class F, class... L&gt;
1095     using mp_transform = typename mp_transform_impl&lt;F, L...&gt;::type;</code></pre>
1096 </div>
1097 </div>
1098 <div class="paragraph">
1099 <p>and then add the unary and binary specializations:</p>
1100 </div>
1101 <div class="listingblock">
1102 <div class="content">
1103 <pre class="highlight"><code>template&lt;template&lt;class...&gt; class F, template&lt;class...&gt; class L, class... T&gt;
1104     struct mp_transform_impl&lt;F, L&lt;T...&gt;&gt;
1105 {
1106     using type = L&lt;F&lt;T&gt;...&gt;;
1107 };
1108
1109 template&lt;template&lt;class...&gt; class F,
1110     template&lt;class...&gt; class L1, class... T1,
1111     template&lt;class...&gt; class L2, class... T2&gt;
1112     struct mp_transform_impl&lt;F, L1&lt;T1...&gt;, L2&lt;T2...&gt;&gt;
1113 {
1114     static_assert( sizeof...(T1) == sizeof...(T2),
1115         "The arguments of mp_transform should be of the same size" );
1116
1117     using type = L1&lt;F&lt;T1,T2&gt;...&gt;;
1118 };</code></pre>
1119 </div>
1120 </div>
1121 <div class="paragraph">
1122 <p>We can also add ternary and further specializations.</p>
1123 </div>
1124 <div class="paragraph">
1125 <p>Is it possible to implement the truly variadic <code>mp_transform</code>, one that works
1126 with an arbitrary number of lists? It is in principle, and I&#8217;ll show one
1127 possible abridged implementation here for completeness:</p>
1128 </div>
1129 <div class="listingblock">
1130 <div class="content">
1131 <pre class="highlight"><code>template&lt;template&lt;class...&gt; class F, class E, class... L&gt;
1132     struct mp_transform_impl;
1133
1134 template&lt;template&lt;class...&gt; class F, class... L&gt;
1135     using mp_transform = typename mp_transform_impl&lt;F, mp_empty&lt;L...&gt;, L...&gt;::type;
1136
1137 template&lt;template&lt;class...&gt; class F, class L1, class... L&gt;
1138     struct mp_transform_impl&lt;F, mp_true, L1, L...&gt;
1139 {
1140     using type = mp_clear&lt;L1&gt;;
1141 };
1142
1143 template&lt;template&lt;class...&gt; class F, class... L&gt;
1144     struct mp_transform_impl&lt;F, mp_false, L...&gt;
1145 {
1146     using _first = F&lt; typename mp_front_impl&lt;L&gt;::type... &gt;;
1147     using _rest = mp_transform&lt; F, typename mp_pop_front_impl&lt;L&gt;::type... &gt;;
1148
1149     using type = mp_push_front&lt;_rest, _first&gt;;
1150 };</code></pre>
1151 </div>
1152 </div>
1153 <div class="paragraph">
1154 <p>but will omit the primitives that it uses. These are</p>
1155 </div>
1156 <div class="ulist">
1157 <ul>
1158 <li>
1159 <p><code>mp_true</code>&#8201;&#8212;&#8201;an alias for <code>std::integral_constant&lt;bool, true&gt;</code>.</p>
1160 </li>
1161 <li>
1162 <p><code>mp_false</code>&#8201;&#8212;&#8201;an alias for <code>std::integral_constant&lt;bool, false&gt;</code>.</p>
1163 </li>
1164 <li>
1165 <p><code>mp_empty&lt;L...&gt;</code>&#8201;&#8212;&#8201;returns <code>mp_true</code> if all lists are empty, <code>mp_false</code>
1166 otherwise.</p>
1167 </li>
1168 <li>
1169 <p><code>mp_clear&lt;L&gt;</code>&#8201;&#8212;&#8201;returns an empty list of the same type as <code>L</code>.</p>
1170 </li>
1171 <li>
1172 <p><code>mp_front&lt;L&gt;</code>&#8201;&#8212;&#8201;returns the first element of <code>L</code>.</p>
1173 </li>
1174 <li>
1175 <p><code>mp_pop_front&lt;L&gt;</code>&#8201;&#8212;&#8201;returns <code>L</code> without its first element.</p>
1176 </li>
1177 </ul>
1178 </div>
1179 <div class="paragraph">
1180 <p>There is one interesting difference between the recursive <code>mp_transform</code>
1181 implementation and the language-based one. <code>mp_transform&lt;add_pointer,
1182 std::pair&lt;int, float&gt;&gt;</code> works with the <code>F&lt;T&gt;...</code> implementation and fails
1183 with the recursive one, because <code>std::pair</code> is not a real type list and can
1184 only hold exactly two types.</p>
1185 </div>
1186 </div>
1187 </div>
1188 <div class="sect1">
1189 <h2 id="the_infamous_tuple_cat_challenge">The infamous tuple_cat challenge</h2>
1190 <div class="sectionbody">
1191 <div class="paragraph">
1192 <p>Eric Niebler, in his
1193 <a href="http://ericniebler.com/2014/11/13/tiny-metaprogramming-library/">Tiny
1194 Metaprogramming Library</a> article, gives the function
1195 <a href="http://en.cppreference.com/w/cpp/utility/tuple/tuple_cat"><code>std::tuple_cat</code></a> as a
1196 kind of a metaprogramming challenge. <code>tuple_cat</code> is a variadic template
1197 function that takes a number of tuples and concatenates them into another
1198 <code>std::tuple</code>. This is Eric&#8217;s solution:</p>
1199 </div>
1200 <div class="listingblock">
1201 <div class="content">
1202 <pre class="highlight"><code>namespace detail
1203 {
1204     template&lt;typename Ret, typename...Is, typename ...Ks,
1205         typename Tuples&gt;
1206     Ret tuple_cat_(typelist&lt;Is...&gt;, typelist&lt;Ks...&gt;,
1207         Tuples tpls)
1208     {
1209         return Ret{std::get&lt;Ks::value&gt;(
1210             std::get&lt;Is::value&gt;(tpls))...};
1211     }
1212 }
1213
1214 template&lt;typename...Tuples,
1215     typename Res =
1216         typelist_apply_t&lt;
1217             meta_quote&lt;std::tuple&gt;,
1218             typelist_cat_t&lt;typelist&lt;as_typelist_t&lt;Tuples&gt;...&gt; &gt; &gt; &gt;
1219 Res tuple_cat(Tuples &amp;&amp;... tpls)
1220 {
1221     static constexpr std::size_t N = sizeof...(Tuples);
1222     // E.g. [0,0,0,2,2,2,3,3]
1223     using inner =
1224         typelist_cat_t&lt;
1225             typelist_transform_t&lt;
1226                 typelist&lt;as_typelist_t&lt;Tuples&gt;...&gt;,
1227                 typelist_transform_t&lt;
1228                     as_typelist_t&lt;make_index_sequence&lt;N&gt; &gt;,
1229                     meta_quote&lt;meta_always&gt; &gt;,
1230                 meta_quote&lt;typelist_transform_t&gt; &gt; &gt;;
1231     // E.g. [0,1,2,0,1,2,0,1]
1232     using outer =
1233         typelist_cat_t&lt;
1234             typelist_transform_t&lt;
1235                 typelist&lt;as_typelist_t&lt;Tuples&gt;...&gt;,
1236                 meta_compose&lt;
1237                     meta_quote&lt;as_typelist_t&gt;,
1238                     meta_quote_i&lt;std::size_t, make_index_sequence&gt;,
1239                     meta_quote&lt;typelist_size_t&gt; &gt; &gt; &gt;;
1240     return detail::tuple_cat_&lt;Res&gt;(
1241         inner{},
1242         outer{},
1243         std::forward_as_tuple(std::forward&lt;Tuples&gt;(tpls)...));
1244 }</code></pre>
1245 </div>
1246 </div>
1247 <div class="paragraph">
1248 <p>All right, challenge accepted. Let&#8217;s see what we can do.</p>
1249 </div>
1250 <div class="paragraph">
1251 <p>As Eric explains, this implementation relies on the clever trick of packing the
1252 input tuples into a tuple, creating two arrays of indices, <code>inner</code> and <code>outer</code>,
1253 then indexing the outer tuple with the outer indices and the result, which is
1254 one of our input tuples, with the inner indices.</p>
1255 </div>
1256 <div class="paragraph">
1257 <p>So, for example, if tuple_cat is invoked as</p>
1258 </div>
1259 <div class="listingblock">
1260 <div class="content">
1261 <pre class="highlight"><code>std::tuple&lt;int, short, long&gt; t1;
1262 std::tuple&lt;&gt; t2;
1263 std::tuple&lt;float, double, long double&gt; t3;
1264 std::tuple&lt;void*, char*&gt; t4;
1265
1266 auto res = tuple_cat(t1, t2, t3, t4);</code></pre>
1267 </div>
1268 </div>
1269 <div class="paragraph">
1270 <p>we&#8217;ll create the tuple</p>
1271 </div>
1272 <div class="listingblock">
1273 <div class="content">
1274 <pre class="highlight"><code>std::tuple&lt;std::tuple&lt;int, short, long&gt;, std::tuple&lt;&gt;,
1275     std::tuple&lt;float, double, long double&gt;, std::tuple&lt;void*, char*&gt;&gt; t{t1, t2, t3, t4};</code></pre>
1276 </div>
1277 </div>
1278 <div class="paragraph">
1279 <p>and then extract the elements of t via</p>
1280 </div>
1281 <div class="listingblock">
1282 <div class="content">
1283 <pre class="highlight"><code>std::get&lt;0&gt;(std::get&lt;0&gt;(t)), // t1[0]
1284 std::get&lt;1&gt;(std::get&lt;0&gt;(t)), // t1[1]
1285 std::get&lt;2&gt;(std::get&lt;0&gt;(t)), // t1[2]
1286 std::get&lt;0&gt;(std::get&lt;2&gt;(t)), // t3[0]
1287 std::get&lt;1&gt;(std::get&lt;2&gt;(t)), // t3[1]
1288 std::get&lt;2&gt;(std::get&lt;2&gt;(t)), // t3[2]
1289 std::get&lt;0&gt;(std::get&lt;3&gt;(t)), // t4[0]
1290 std::get&lt;1&gt;(std::get&lt;3&gt;(t)), // t4[1]</code></pre>
1291 </div>
1292 </div>
1293 <div class="paragraph">
1294 <p>(<code>t2</code> is empty, so we take nothing from it.)</p>
1295 </div>
1296 <div class="paragraph">
1297 <p>The first column of integers is the <code>outer</code> array, the second one - the <code>inner</code>
1298 array, and these are what we need to compute. But first, let&#8217;s deal with the
1299 return type of <code>tuple_cat</code>.</p>
1300 </div>
1301 <div class="paragraph">
1302 <p>The return type of <code>tuple_cat</code> is just the concatenation of the arguments,
1303 viewed as type lists. The metaprogramming algorithm that concatenates lists is
1304 called
1305 <a href="https://ericniebler.github.io/meta/group__transformation.html"><code>meta::concat</code></a>
1306 in Eric Niebler&#8217;s <a href="https://github.com/ericniebler/meta">Meta</a> library, but I&#8217;ll
1307 call it <code>mp_append</code>, after its classic Lisp name.</p>
1308 </div>
1309 <div class="paragraph">
1310 <p>(Lisp is today&#8217;s equivalent of Latin. Educated people are supposed to have
1311 studied and forgotten it.)</p>
1312 </div>
1313 <div class="listingblock">
1314 <div class="content">
1315 <pre class="highlight"><code>template&lt;class... L&gt; struct mp_append_impl;
1316
1317 template&lt;class... L&gt; using mp_append = typename mp_append_impl&lt;L...&gt;::type;
1318
1319 template&lt;&gt; struct mp_append_impl&lt;&gt;
1320 {
1321     using type = mp_list&lt;&gt;;
1322 };
1323
1324 template&lt;template&lt;class...&gt; class L, class... T&gt; struct mp_append_impl&lt;L&lt;T...&gt;&gt;
1325 {
1326     using type = L&lt;T...&gt;;
1327 };
1328
1329 template&lt;template&lt;class...&gt; class L1, class... T1,
1330     template&lt;class...&gt; class L2, class... T2, class... Lr&gt;
1331     struct mp_append_impl&lt;L1&lt;T1...&gt;, L2&lt;T2...&gt;, Lr...&gt;
1332 {
1333     using type = mp_append&lt;L1&lt;T1..., T2...&gt;, Lr...&gt;;
1334 };</code></pre>
1335 </div>
1336 </div>
1337 <div class="paragraph">
1338 <p>That was fairly easy. There are other ways to implement <code>mp_append</code>, but this
1339 one demonstrates how the language does most of the work for us via pack
1340 expansion. This is a common theme in C&#43;&#43;11.</p>
1341 </div>
1342 <div class="paragraph">
1343 <p>Note how <code>mp_append</code> returns the same list type as its first argument. Of
1344 course, in the case in which no arguments are given, there is no first argument
1345 from which to take the type, so I&#8217;ve arbitrarily chosen to return an empty
1346 <code>mp_list</code>.</p>
1347 </div>
1348 <div class="paragraph">
1349 <p>We&#8217;re now ready with the declaration of <code>tuple_cat</code>:</p>
1350 </div>
1351 <div class="listingblock">
1352 <div class="content">
1353 <pre class="highlight"><code>template&lt;class... Tp,
1354     class R = mp_append&lt;typename std::remove_reference&lt;Tp&gt;::type...&gt;&gt;
1355     R tuple_cat( Tp &amp;&amp;... tp );</code></pre>
1356 </div>
1357 </div>
1358 <div class="paragraph">
1359 <p>The reason we need <code>remove_reference</code> is because of the rvalue reference
1360 parameters, used to implement perfect forwarding. If the argument is an lvalue,
1361 such as for example <code>t1</code> above, its corresponding type will be a reference to a
1362 tuple&#8201;&#8212;&#8201;<code>std::tuple&lt;int, short, long&gt;&amp;</code> in <code>t1</code>'s case. Our primitives do
1363 not recognize references to tuples as type lists, so we need to strip them off.</p>
1364 </div>
1365 <div class="paragraph">
1366 <p>There are two problems with our return type computation though. One, what if
1367 <code>tuple_cat</code> is called without any arguments? We return <code>mp_list&lt;&gt;</code> in that
1368 case, but the correct result is <code>std::tuple&lt;&gt;</code>.</p>
1369 </div>
1370 <div class="paragraph">
1371 <p>Two, what if we call <code>tuple_cat</code> with a first argument that is a <code>std::pair</code>?
1372 We&#8217;ll try to append more elements to <code>std::pair</code>, and it will fail.</p>
1373 </div>
1374 <div class="paragraph">
1375 <p>We can solve both our problems by using an empty tuple as the first argument to
1376 <code>mp_append</code>:</p>
1377 </div>
1378 <div class="listingblock">
1379 <div class="content">
1380 <pre class="highlight"><code>template&lt;class... Tp,
1381     class R = mp_append&lt;std::tuple&lt;&gt;, typename std::remove_reference&lt;Tp&gt;::type...&gt;&gt;
1382     R tuple_cat( Tp &amp;&amp;... tp );</code></pre>
1383 </div>
1384 </div>
1385 <div class="paragraph">
1386 <p>With the return type taken care of, let&#8217;s now move on to computing inner. We
1387 have</p>
1388 </div>
1389 <div class="listingblock">
1390 <div class="content">
1391 <pre class="highlight"><code>[x1, x2, x3], [], [y1, y2, y3], [z1, z2]</code></pre>
1392 </div>
1393 </div>
1394 <div class="paragraph">
1395 <p>as input and we need to output</p>
1396 </div>
1397 <div class="listingblock">
1398 <div class="content">
1399 <pre class="highlight"><code>[0, 0, 0, 2, 2, 2, 3, 3]</code></pre>
1400 </div>
1401 </div>
1402 <div class="paragraph">
1403 <p>which is the concatenation of</p>
1404 </div>
1405 <div class="listingblock">
1406 <div class="content">
1407 <pre class="highlight"><code>[0, 0, 0], [], [2, 2, 2], [3, 3]</code></pre>
1408 </div>
1409 </div>
1410 <div class="paragraph">
1411 <p>Here each tuple is the same size as the input, but is filled with a constant
1412 that represents its index in the argument list. The first tuple is filled with
1413 0, the second with 1, the third with 2, and so on.</p>
1414 </div>
1415 <div class="paragraph">
1416 <p>We can achieve this result if we first compute a list of indices, in our case
1417 <code>[0, 1, 2, 3]</code>, then use binary <code>mp_transform</code> on the two lists</p>
1418 </div>
1419 <div class="listingblock">
1420 <div class="content">
1421 <pre class="highlight"><code>[[x1, x2, x3], [], [y1, y2, y3], [z1, z2]]
1422 [0, 1, 2, 3]</code></pre>
1423 </div>
1424 </div>
1425 <div class="paragraph">
1426 <p>and a function which takes a list and an integer (in the form of an
1427 <code>std::integral_constant</code>) and returns a list that is the same size as the
1428 original, but filled with the second argument.</p>
1429 </div>
1430 <div class="paragraph">
1431 <p>We&#8217;ll call this function <code>mp_fill</code>, after <code>std::fill</code>.</p>
1432 </div>
1433 <div class="paragraph">
1434 <p>Functional programmers will immediately realize that <code>mp_fill</code> is
1435 <code>mp_transform</code> with a function that returns a constant, and here&#8217;s an
1436 implementation along these lines:</p>
1437 </div>
1438 <div class="listingblock">
1439 <div class="content">
1440 <pre class="highlight"><code>template&lt;class V&gt; struct mp_constant
1441 {
1442     template&lt;class...&gt; using apply = V;
1443 };
1444
1445 template&lt;class L, class V&gt;
1446     using mp_fill = mp_transform&lt;mp_constant&lt;V&gt;::template apply, L&gt;;</code></pre>
1447 </div>
1448 </div>
1449 <div class="paragraph">
1450 <p>Here&#8217;s an alternate implementation:</p>
1451 </div>
1452 <div class="listingblock">
1453 <div class="content">
1454 <pre class="highlight"><code>template&lt;class L, class V&gt; struct mp_fill_impl;
1455
1456 template&lt;template&lt;class...&gt; class L, class... T, class V&gt;
1457     struct mp_fill_impl&lt;L&lt;T...&gt;, V&gt;
1458 {
1459     template&lt;class...&gt; using _fv = V;
1460     using type = L&lt;_fv&lt;T&gt;...&gt;;
1461 };
1462
1463 template&lt;class L, class V&gt; using mp_fill = typename mp_fill_impl&lt;L, V&gt;::type;</code></pre>
1464 </div>
1465 </div>
1466 <div class="paragraph">
1467 <p>These demonstrate different styles and choosing one over the other is largely a
1468 matter of taste here. In the first case, we combine existing primitives; in the
1469 second case, we "inline" <code>mp_const</code> and even <code>mp_transform</code> in the body of
1470 <code>mp_fill_impl</code>.</p>
1471 </div>
1472 <div class="paragraph">
1473 <p>Most C&#43;&#43;11 programmers will probably find the second implementation easier to
1474 read.</p>
1475 </div>
1476 <div class="paragraph">
1477 <p>We can now <code>mp_fill</code>, but we still need the <code>[0, 1, 2, 3]</code> index sequence. We
1478 could write an algorithm <code>mp_iota</code> for that (named after
1479 <a href="http://en.cppreference.com/w/cpp/algorithm/iota"><code>std::iota</code></a>), but it so
1480 happens that C&#43;&#43;14 already has a standard way of generating an index
1481 sequence, called
1482 <a href="http://en.cppreference.com/w/cpp/utility/integer_sequence"><code>std::make_index_sequence</code></a>.
1483 Since Eric&#8217;s original solution makes use of <code>make_index_sequence</code>, let&#8217;s follow
1484 his lead.</p>
1485 </div>
1486 <div class="paragraph">
1487 <p>Technically, this takes us outside of C&#43;&#43;11, but <code>make_index_sequence</code> is not
1488 hard to implement (if efficiency is not a concern):</p>
1489 </div>
1490 <div class="listingblock">
1491 <div class="content">
1492 <pre class="highlight"><code>template&lt;class T, T... Ints&gt; struct integer_sequence
1493 {
1494 };
1495
1496 template&lt;class S&gt; struct next_integer_sequence;
1497
1498 template&lt;class T, T... Ints&gt; struct next_integer_sequence&lt;integer_sequence&lt;T, Ints...&gt;&gt;
1499 {
1500     using type = integer_sequence&lt;T, Ints..., sizeof...(Ints)&gt;;
1501 };
1502
1503 template&lt;class T, T I, T N&gt; struct make_int_seq_impl;
1504
1505 template&lt;class T, T N&gt;
1506     using make_integer_sequence = typename make_int_seq_impl&lt;T, 0, N&gt;::type;
1507
1508 template&lt;class T, T I, T N&gt; struct make_int_seq_impl
1509 {
1510     using type = typename next_integer_sequence&lt;
1511         typename make_int_seq_impl&lt;T, I+1, N&gt;::type&gt;::type;
1512 };
1513
1514 template&lt;class T, T N&gt; struct make_int_seq_impl&lt;T, N, N&gt;
1515 {
1516     using type = integer_sequence&lt;T&gt;;
1517 };
1518
1519 template&lt;std::size_t... Ints&gt;
1520     using index_sequence = integer_sequence&lt;std::size_t, Ints...&gt;;
1521
1522 template&lt;std::size_t N&gt;
1523     using make_index_sequence = make_integer_sequence&lt;std::size_t, N&gt;;</code></pre>
1524 </div>
1525 </div>
1526 <div class="paragraph">
1527 <p>We can now obtain an <code>index_sequence&lt;0, 1, 2, 3&gt;</code>:</p>
1528 </div>
1529 <div class="listingblock">
1530 <div class="content">
1531 <pre class="highlight"><code>template&lt;class... Tp,
1532     class R = mp_append&lt;std::tuple&lt;&gt;, typename std::remove_reference&lt;Tp&gt;::type...&gt;&gt;
1533     R tuple_cat( Tp &amp;&amp;... tp )
1534 {
1535     std::size_t const N = sizeof...(Tp);
1536
1537     // inner
1538
1539     using seq = make_index_sequence&lt;N&gt;;
1540 }</code></pre>
1541 </div>
1542 </div>
1543 <div class="paragraph">
1544 <p>but <code>make_index_sequence&lt;4&gt;</code> returns <code>integer_sequence&lt;std::size_t, 0, 1, 2,
1545 3&gt;</code>, which is not a type list. In order to work with it, we need to convert it
1546 to a type list, so we&#8217;ll introduce a function <code>mp_from_sequence</code> that does
1547 that.</p>
1548 </div>
1549 <div class="listingblock">
1550 <div class="content">
1551 <pre class="highlight"><code>template&lt;class S&gt; struct mp_from_sequence_impl;
1552
1553 template&lt;template&lt;class T, T... I&gt; class S, class U, U... J&gt;
1554     struct mp_from_sequence_impl&lt;S&lt;U, J...&gt;&gt;
1555 {
1556     using type = mp_list&lt;std::integral_constant&lt;U, J&gt;...&gt;;
1557 };
1558
1559 template&lt;class S&gt; using mp_from_sequence = typename mp_from_sequence_impl&lt;S&gt;::type;</code></pre>
1560 </div>
1561 </div>
1562 <div class="paragraph">
1563 <p>We can now compute the two lists that we wanted to transform with <code>mp_fill</code>:</p>
1564 </div>
1565 <div class="listingblock">
1566 <div class="content">
1567 <pre class="highlight"><code>template&lt;class... Tp,
1568     class R = mp_append&lt;std::tuple&lt;&gt;, typename std::remove_reference&lt;Tp&gt;::type...&gt;&gt;
1569     R tuple_cat( Tp &amp;&amp;... tp )
1570 {
1571     std::size_t const N = sizeof...(Tp);
1572
1573     // inner
1574
1575     using list1 = mp_list&lt;typename std::remove_reference&lt;Tp&gt;::type...&gt;;
1576     using list2 = mp_from_sequence&lt;make_index_sequence&lt;N&gt;&gt;;
1577
1578     // list1: [[x1, x2, x3], [], [y1, y2, y3], [z1, z2]]
1579     // list2: [0, 1, 2, 3]
1580
1581     return R{};
1582 }</code></pre>
1583 </div>
1584 </div>
1585 <div class="paragraph">
1586 <p>and finish the job of computing <code>inner</code>:</p>
1587 </div>
1588 <div class="listingblock">
1589 <div class="content">
1590 <pre class="highlight"><code>template&lt;class... Tp,
1591     class R = mp_append&lt;std::tuple&lt;&gt;, typename std::remove_reference&lt;Tp&gt;::type...&gt;&gt;
1592     R tuple_cat( Tp &amp;&amp;... tp )
1593 {
1594     std::size_t const N = sizeof...(Tp);
1595
1596     // inner
1597
1598     using list1 = mp_list&lt;typename std::remove_reference&lt;Tp&gt;::type...&gt;;
1599     using list2 = mp_from_sequence&lt;make_index_sequence&lt;N&gt;&gt;;
1600
1601     // list1: [[x1, x2, x3], [], [y1, y2, y3], [z1, z2]]
1602     // list2: [0, 1, 2, 3]
1603
1604     using list3 = mp_transform&lt;mp_fill, list1, list2&gt;;
1605
1606     // list3: [[0, 0, 0], [], [2, 2, 2], [3, 3]]
1607
1608     using inner = mp_rename&lt;list3, mp_append&gt;; // or mp_apply&lt;mp_append, list3&gt;
1609
1610     // inner: [0, 0, 0, 2, 2, 2, 3, 3]
1611
1612     return R{};
1613 }</code></pre>
1614 </div>
1615 </div>
1616 <div class="paragraph">
1617 <p>For <code>outer</code>, we again have</p>
1618 </div>
1619 <div class="listingblock">
1620 <div class="content">
1621 <pre class="highlight"><code>[x1, x2, x3], [], [y1, y2, y3], [z1, z2]</code></pre>
1622 </div>
1623 </div>
1624 <div class="paragraph">
1625 <p>as input and we need to output</p>
1626 </div>
1627 <div class="listingblock">
1628 <div class="content">
1629 <pre class="highlight"><code>[0, 1, 2, 0, 1, 2, 0, 1]</code></pre>
1630 </div>
1631 </div>
1632 <div class="paragraph">
1633 <p>which is the concatenation of</p>
1634 </div>
1635 <div class="listingblock">
1636 <div class="content">
1637 <pre class="highlight"><code>[0, 1, 2], [], [0, 1, 2], [0, 1]</code></pre>
1638 </div>
1639 </div>
1640 <div class="paragraph">
1641 <p>The difference here is that instead of filling the tuple with a constant value,
1642 we need to fill it with increasing values, starting from 0, that is, with the
1643 result of <code>make_index_sequence&lt;N&gt;</code>, where <code>N</code> is the number of elements.</p>
1644 </div>
1645 <div class="paragraph">
1646 <p>The straightforward way to do that is to just define a metafunction <code>F</code> that
1647 does what we want, then use <code>mp_transform</code> to apply it to the input:</p>
1648 </div>
1649 <div class="listingblock">
1650 <div class="content">
1651 <pre class="highlight"><code>template&lt;class N&gt; using mp_iota = mp_from_sequence&lt;make_index_sequence&lt;N::value&gt;&gt;;
1652
1653 template&lt;class L&gt; using F = mp_iota&lt;mp_size&lt;L&gt;&gt;;
1654
1655 template&lt;class... Tp,
1656     class R = mp_append&lt;std::tuple&lt;&gt;, typename std::remove_reference&lt;Tp&gt;::type...&gt;&gt;
1657     R tuple_cat( Tp &amp;&amp;... tp )
1658 {
1659     std::size_t const N = sizeof...(Tp);
1660
1661     // outer
1662
1663     using list1 = mp_list&lt;typename std::remove_reference&lt;Tp&gt;::type...&gt;;
1664     using list2 = mp_transform&lt;F, list1&gt;;
1665
1666     // list2: [[0, 1, 2], [], [0, 1, 2], [0, 1]]
1667
1668     using outer = mp_rename&lt;list2, mp_append&gt;;
1669
1670     // outer: [0, 1, 2, 0, 1, 2, 0, 1]
1671
1672     return R{};
1673 }</code></pre>
1674 </div>
1675 </div>
1676 <div class="paragraph">
1677 <p>Well that was easy. Surprisingly easy. The one small annoyance is that we can&#8217;t
1678 define <code>F</code> inside <code>tuple_cat</code> - templates can&#8217;t be defined in functions.</p>
1679 </div>
1680 <div class="paragraph">
1681 <p>Let&#8217;s put everything together.</p>
1682 </div>
1683 <div class="listingblock">
1684 <div class="content">
1685 <pre class="highlight"><code>template&lt;class N&gt; using mp_iota = mp_from_sequence&lt;make_index_sequence&lt;N::value&gt;&gt;;
1686
1687 template&lt;class L&gt; using F = mp_iota&lt;mp_size&lt;L&gt;&gt;;
1688
1689 template&lt;class R, class...Is, class... Ks, class Tp&gt;
1690 R tuple_cat_( mp_list&lt;Is...&gt;, mp_list&lt;Ks...&gt;, Tp tp )
1691 {
1692     return R{ std::get&lt;Ks::value&gt;(std::get&lt;Is::value&gt;(tp))... };
1693 }
1694
1695 template&lt;class... Tp,
1696     class R = mp_append&lt;std::tuple&lt;&gt;, typename std::remove_reference&lt;Tp&gt;::type...&gt;&gt;
1697     R tuple_cat( Tp &amp;&amp;... tp )
1698 {
1699     std::size_t const N = sizeof...(Tp);
1700
1701     // inner
1702
1703     using list1 = mp_list&lt;typename std::remove_reference&lt;Tp&gt;::type...&gt;;
1704     using list2 = mp_from_sequence&lt;make_index_sequence&lt;N&gt;&gt;;
1705
1706     // list1: [[x1, x2, x3], [], [y1, y2, y3], [z1, z2]]
1707     // list2: [0, 1, 2, 3]
1708
1709     using list3 = mp_transform&lt;mp_fill, list1, list2&gt;;
1710
1711     // list3: [[0, 0, 0], [], [2, 2, 2], [3, 3]]
1712
1713     using inner = mp_rename&lt;list3, mp_append&gt;; // or mp_apply&lt;mp_append, list3&gt;
1714
1715     // inner: [0, 0, 0, 2, 2, 2, 3, 3]
1716
1717     // outer
1718
1719     using list4 = mp_transform&lt;F, list1&gt;;
1720
1721     // list4: [[0, 1, 2], [], [0, 1, 2], [0, 1]]
1722
1723     using outer = mp_rename&lt;list4, mp_append&gt;;
1724
1725     // outer: [0, 1, 2, 0, 1, 2, 0, 1]
1726
1727     return tuple_cat_&lt;R&gt;( inner(), outer(),
1728         std::forward_as_tuple( std::forward&lt;Tp&gt;(tp)... ) );
1729 }</code></pre>
1730 </div>
1731 </div>
1732 <div class="paragraph">
1733 <p>This almost compiles, except that our <code>inner</code> happens to be a <code>std::tuple</code>, but
1734 our helper function expects an <code>mp_list</code>. (<code>outer</code> is already an <code>mp_list</code>, by
1735 sheer luck.) We can fix that easily enough.</p>
1736 </div>
1737 <div class="listingblock">
1738 <div class="content">
1739 <pre class="highlight"><code>return tuple_cat_&lt;R&gt;( mp_rename&lt;inner, mp_list&gt;(), outer(),
1740     std::forward_as_tuple( std::forward&lt;Tp&gt;(tp)... ) );</code></pre>
1741 </div>
1742 </div>
1743 <div class="paragraph">
1744 <p>Let&#8217;s define a <code>print_tuple</code> function and see if everything checks out.</p>
1745 </div>
1746 <div class="listingblock">
1747 <div class="content">
1748 <pre class="highlight"><code>template&lt;int I, int N, class... T&gt; struct print_tuple_
1749 {
1750     void operator()( std::tuple&lt;T...&gt; const &amp; tp ) const
1751     {
1752         using Tp = typename std::tuple_element&lt;I, std::tuple&lt;T...&gt;&gt;::type;
1753
1754         print_type&lt;Tp&gt;( " ", ": " );
1755
1756         std::cout &lt;&lt; std::get&lt;I&gt;( tp ) &lt;&lt; ";";
1757
1758         print_tuple_&lt; I+1, N, T... &gt;()( tp );
1759     }
1760 };
1761
1762 template&lt;int N, class... T&gt; struct print_tuple_&lt;N, N, T...&gt;
1763 {
1764     void operator()( std::tuple&lt;T...&gt; const &amp; ) const
1765     {
1766     }
1767 };
1768
1769 template&lt;class... T&gt; void print_tuple( std::tuple&lt;T...&gt; const &amp; tp )
1770 {
1771     std::cout &lt;&lt; "{";
1772     print_tuple_&lt;0, sizeof...(T), T...&gt;()( tp );
1773     std::cout &lt;&lt; " }\n";
1774 }
1775
1776 int main()
1777 {
1778     std::tuple&lt;int, long&gt; t1{ 1, 2 };
1779     std::tuple&lt;&gt; t2;
1780     std::tuple&lt;float, double, long double&gt; t3{ 3, 4, 5 };
1781     std::pair&lt;void const*, char const*&gt; t4{ "pv", "test" };
1782
1783     using expected = std::tuple&lt;int, long, float, double, long double,
1784         void const*, char const*&gt;;
1785
1786     auto result = ::tuple_cat( t1, t2, t3, t4 );
1787
1788     static_assert( std::is_same&lt;decltype(result), expected&gt;::value, "" );
1789
1790     print_tuple( result );
1791 }</code></pre>
1792 </div>
1793 </div>
1794 <div class="paragraph">
1795 <p>Output:</p>
1796 </div>
1797 <div class="listingblock">
1798 <div class="content">
1799 <pre class="highlight"><code>{ int: 1; long: 2; float: 3; double: 4; long double: 5; void const*: 0x407086;
1800     char const*: test; }</code></pre>
1801 </div>
1802 </div>
1803 <div class="paragraph">
1804 <p>Seems to work. But there&#8217;s at least one error left. To see why, replace the
1805 first tuple</p>
1806 </div>
1807 <div class="listingblock">
1808 <div class="content">
1809 <pre class="highlight"><code>std::tuple&lt;int, long&gt; t1{ 1, 2 };</code></pre>
1810 </div>
1811 </div>
1812 <div class="paragraph">
1813 <p>with a pair:</p>
1814 </div>
1815 <div class="listingblock">
1816 <div class="content">
1817 <pre class="highlight"><code>std::pair&lt;int, long&gt; t1{ 1, 2 };</code></pre>
1818 </div>
1819 </div>
1820 <div class="paragraph">
1821 <p>We now get an error at</p>
1822 </div>
1823 <div class="listingblock">
1824 <div class="content">
1825 <pre class="highlight"><code>using inner = mp_rename&lt;list3, mp_append&gt;;</code></pre>
1826 </div>
1827 </div>
1828 <div class="paragraph">
1829 <p>because the first element of <code>list3</code> is an <code>std::pair</code>, which <code>mp_append</code> tries
1830 and fails to use as its return type.</p>
1831 </div>
1832 <div class="paragraph">
1833 <p>There are two ways to fix that. The first one is to apply the same trick we
1834 used for the return type, and insert an empty <code>mp_list</code> at the front of
1835 <code>list3</code>, which <code>mp_append</code> will use as a return type:</p>
1836 </div>
1837 <div class="listingblock">
1838 <div class="content">
1839 <pre class="highlight"><code>using inner = mp_rename&lt;mp_push_front&lt;list3, mp_list&lt;&gt;&gt;, mp_append&gt;;</code></pre>
1840 </div>
1841 </div>
1842 <div class="paragraph">
1843 <p>The second way is to just convert all inputs to mp_list:</p>
1844 </div>
1845 <div class="listingblock">
1846 <div class="content">
1847 <pre class="highlight"><code>using list1 = mp_list&lt;
1848     mp_rename&lt;typename std::remove_reference&lt;Tp&gt;::type, mp_list&gt;...&gt;;</code></pre>
1849 </div>
1850 </div>
1851 <div class="paragraph">
1852 <p>In both cases, inner will now be an <code>mp_list</code>, so we can omit the <code>mp_rename</code>
1853 in the call to <code>tuple_cat_</code>.</p>
1854 </div>
1855 <div class="paragraph">
1856 <p>We&#8217;re done. The results hopefully speak for themselves.</p>
1857 </div>
1858 </div>
1859 </div>
1860 <div class="sect1">
1861 <h2 id="higher_order_metaprogramming_or_lack_thereof">Higher order metaprogramming, or lack thereof</h2>
1862 <div class="sectionbody">
1863 <div class="paragraph">
1864 <p>Perhaps by now you&#8217;re wondering why this article is called "Simple C&#43;&#43;11
1865 metaprogramming", since what we covered so far wasn&#8217;t particularly simple.</p>
1866 </div>
1867 <div class="paragraph">
1868 <p>The <em>relative</em> simplicity of our approach stems from the fact that we&#8217;ve not
1869 been doing any higher order metaprogramming, that is, we haven&#8217;t introduced any
1870 primitives that return metafunctions, such as <code>compose</code>, <code>bind</code>, or a lambda
1871 library.</p>
1872 </div>
1873 <div class="paragraph">
1874 <p>I posit that such higher order metaprogramming is, in the majority of cases,
1875 not necessary in C&#43;&#43;11. Consider, for example, Eric Niebler&#8217;s solution given
1876 above:</p>
1877 </div>
1878 <div class="listingblock">
1879 <div class="content">
1880 <pre class="highlight"><code>using outer =
1881     typelist_cat_t&lt;
1882         typelist_transform_t&lt;
1883             typelist&lt;as_typelist_t&lt;Tuples&gt;...&gt;,
1884             meta_compose&lt;
1885                 meta_quote&lt;as_typelist_t&gt;,
1886                 meta_quote_i&lt;std::size_t, make_index_sequence&gt;,
1887                 meta_quote&lt;typelist_size_t&gt; &gt; &gt; &gt;;</code></pre>
1888 </div>
1889 </div>
1890 <div class="paragraph">
1891 <p>The <code>meta_compose</code> expression takes three other ("quoted") metafunctions and
1892 creates a new metafunction that applies them in order. Eric uses this example
1893 as motivation to introduce the concept of a "metafunction class" and then to
1894 supply various primitives that operate on metafunction classes.</p>
1895 </div>
1896 <div class="paragraph">
1897 <p>But when we have metafunctions <code>F</code>, <code>G</code> and <code>H</code>, instead of using
1898 <code>meta_compose</code>, in C&#43;&#43;11 we can just do</p>
1899 </div>
1900 <div class="listingblock">
1901 <div class="content">
1902 <pre class="highlight"><code>template&lt;class... T&gt; using Fgh = F&lt;G&lt;H&lt;T...&gt;&gt;&gt;;</code></pre>
1903 </div>
1904 </div>
1905 <div class="paragraph">
1906 <p>and that&#8217;s it. The language makes defining composite functions easy, and there
1907 is no need for library support. If the functions to be composed are
1908 <code>as_typelist_t</code>, <code>std::make_index_sequence</code> and <code>typelist_size_t</code>, we just
1909 define</p>
1910 </div>
1911 <div class="listingblock">
1912 <div class="content">
1913 <pre class="highlight"><code>template&lt;class... T&gt;
1914     using F = as_typelist_t&lt;std::make_index_sequence&lt;typelist_size_t&lt;T...&gt;::value&gt;&gt;;</code></pre>
1915 </div>
1916 </div>
1917 <div class="paragraph">
1918 <p>Similarly, if we need a metafunction that will return <code>sizeof(T) &lt; sizeof(U)</code>,
1919 there is no need to enlist a metaprogramming lambda library as in</p>
1920 </div>
1921 <div class="listingblock">
1922 <div class="content">
1923 <pre class="highlight"><code>lambda&lt;_a, _b, less&lt;sizeof_&lt;_a&gt;, sizeof_&lt;_b&gt;&gt;&gt;&gt;</code></pre>
1924 </div>
1925 </div>
1926 <div class="paragraph">
1927 <p>We could just define it inline:</p>
1928 </div>
1929 <div class="listingblock">
1930 <div class="content">
1931 <pre class="highlight"><code>template&lt;class T, class U&gt; using sizeof_less = mp_bool&lt;(sizeof(T) &lt; sizeof(U))&gt;;</code></pre>
1932 </div>
1933 </div>
1934 </div>
1935 </div>
1936 <div class="sect1">
1937 <h2 id="one_more_thing">One more thing</h2>
1938 <div class="sectionbody">
1939 <div class="paragraph">
1940 <p>Finally, let me show the implementations of <code>mp_count</code> and <code>mp_count_if</code>, for
1941 no reason other than I find them interesting. <code>mp_count&lt;L, V&gt;</code> returns the
1942 number of occurrences of the type <code>V</code> in the list <code>L</code>; <code>mp_count_if&lt;L, P&gt;</code>
1943 counts the number of types in <code>L</code> for which <code>P&lt;T&gt;</code> is <code>true</code>.</p>
1944 </div>
1945 <div class="paragraph">
1946 <p>As a first step, I&#8217;ll implement <code>mp_plus</code>. <code>mp_plus</code> is a variadic (not just
1947 binary) metafunction that returns the sum of its arguments.</p>
1948 </div>
1949 <div class="listingblock">
1950 <div class="content">
1951 <pre class="highlight"><code>template&lt;class... T&gt; struct mp_plus_impl;
1952
1953 template&lt;class... T&gt; using mp_plus = typename mp_plus_impl&lt;T...&gt;::type;
1954
1955 template&lt;&gt; struct mp_plus_impl&lt;&gt;
1956 {
1957     using type = std::integral_constant&lt;int, 0&gt;;
1958 };
1959
1960 template&lt;class T1, class... T&gt; struct mp_plus_impl&lt;T1, T...&gt;
1961 {
1962     static constexpr auto _v = T1::value + mp_plus&lt;T...&gt;::value;
1963
1964     using type = std::integral_constant&lt;
1965         typename std::remove_const&lt;decltype(_v)&gt;::type, _v&gt;;
1966 };</code></pre>
1967 </div>
1968 </div>
1969 <div class="paragraph">
1970 <p>Now that we have <code>mp_plus</code>, <code>mp_count</code> is just</p>
1971 </div>
1972 <div class="listingblock">
1973 <div class="content">
1974 <pre class="highlight"><code>template&lt;class L, class V&gt; struct mp_count_impl;
1975
1976 template&lt;template&lt;class...&gt; class L, class... T, class V&gt;
1977     struct mp_count_impl&lt;L&lt;T...&gt;, V&gt;
1978 {
1979     using type = mp_plus&lt;std::is_same&lt;T, V&gt;...&gt;;
1980 };
1981
1982 template&lt;class L, class V&gt; using mp_count = typename mp_count_impl&lt;L, V&gt;::type;</code></pre>
1983 </div>
1984 </div>
1985 <div class="paragraph">
1986 <p>This is another illustration of the power of parameter pack expansion. It&#8217;s a
1987 pity that we can&#8217;t use pack expansion in <code>mp_plus</code> as well, to obtain</p>
1988 </div>
1989 <div class="listingblock">
1990 <div class="content">
1991 <pre class="highlight"><code>T1::value + T2::value + T3::value + T4::value + ...</code></pre>
1992 </div>
1993 </div>
1994 <div class="paragraph">
1995 <p>directly. It would have been nice for <code>T::value + ...</code> to have been
1996 supported, and it appears that in C&#43;&#43;17, it will be.</p>
1997 </div>
1998 <div class="paragraph">
1999 <p><code>mp_count_if</code> is similarly straightforward:</p>
2000 </div>
2001 <div class="listingblock">
2002 <div class="content">
2003 <pre class="highlight"><code>template&lt;class L, template&lt;class...&gt; class P&gt; struct mp_count_if_impl;
2004
2005 template&lt;template&lt;class...&gt; class L, class... T, template&lt;class...&gt; class P&gt;
2006     struct mp_count_if_impl&lt;L&lt;T...&gt;, P&gt;
2007 {
2008     using type = mp_plus&lt;P&lt;T&gt;...&gt;;
2009 };
2010
2011 template&lt;class L, template&lt;class...&gt; class P&gt;
2012     using mp_count_if = typename mp_count_if_impl&lt;L, P&gt;::type;</code></pre>
2013 </div>
2014 </div>
2015 <div class="paragraph">
2016 <p>at least if we require <code>P</code> to return <code>bool</code>. If not, we&#8217;ll have to coerce
2017 <code>P&lt;T&gt;::value</code> to 0 or 1, or the count will not be correct.</p>
2018 </div>
2019 <div class="listingblock">
2020 <div class="content">
2021 <pre class="highlight"><code>template&lt;bool v&gt; using mp_bool = std::integral_constant&lt;bool, v&gt;;
2022
2023 template&lt;class L, template&lt;class...&gt; class P&gt; struct mp_count_if_impl;
2024
2025 template&lt;template&lt;class...&gt; class L, class... T, template&lt;class...&gt; class P&gt;
2026     struct mp_count_if_impl&lt;L&lt;T...&gt;, P&gt;
2027 {
2028     using type = mp_plus&lt;mp_bool&lt;P&lt;T&gt;::value != 0&gt;...&gt;;
2029 };
2030
2031 template&lt;class L, template&lt;class...&gt; class P&gt;
2032     using mp_count_if = typename mp_count_if_impl&lt;L, P&gt;::type;</code></pre>
2033 </div>
2034 </div>
2035 <div class="paragraph">
2036 <p>The last primitive I&#8217;ll show is <code>mp_contains</code>. <code>mp_contains&lt;L, V&gt;</code> returns
2037 whether the list <code>L</code> contains the type <code>V</code>:</p>
2038 </div>
2039 <div class="listingblock">
2040 <div class="content">
2041 <pre class="highlight"><code>template&lt;class L, class V&gt; using mp_contains = mp_bool&lt;mp_count&lt;L, V&gt;::value != 0&gt;;</code></pre>
2042 </div>
2043 </div>
2044 <div class="paragraph">
2045 <p>At first sight, this implementation appears horribly naive and inefficient&#8201;&#8212;&#8201;why would we need to count all the occurrences just to throw that away if we&#8217;re
2046 only interested in a boolean result&#8201;&#8212;&#8201;but it&#8217;s actually pretty competitive and
2047 perfectly usable. We just need to add one slight optimization to <code>mp_plus</code>, the
2048 engine behind <code>mp_count</code> and <code>mp_contains</code>:</p>
2049 </div>
2050 <div class="listingblock">
2051 <div class="content">
2052 <pre class="highlight"><code>template&lt;class T1, class T2, class T3, class T4, class T5,
2053     class T6, class T7, class T8, class T9, class T10, class... T&gt;
2054     struct mp_plus_impl&lt;T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...&gt;
2055 {
2056     static constexpr auto _v = T1::value + T2::value + T3::value + T4::value +
2057         T5::value + T6::value + T7::value + T8::value + T9::value + T10::value +
2058         mp_plus&lt;T...&gt;::value;
2059
2060     using type = std::integral_constant&lt;
2061         typename std::remove_const&lt;decltype(_v)&gt;::type, _v&gt;;
2062 };</code></pre>
2063 </div>
2064 </div>
2065 <div class="paragraph">
2066 <p>This cuts the number of template instantiations approximately tenfold.</p>
2067 </div>
2068 </div>
2069 </div>
2070 <div class="sect1">
2071 <h2 id="conclusion">Conclusion</h2>
2072 <div class="sectionbody">
2073 <div class="paragraph">
2074 <p>I have outlined an approach to metaprogramming in C&#43;&#43;11 that</p>
2075 </div>
2076 <div class="ulist">
2077 <ul>
2078 <li>
2079 <p>takes advantage of variadic templates, parameter pack expansion, and template
2080 aliases;</p>
2081 </li>
2082 <li>
2083 <p>operates on any variadic template <code>L&lt;T...&gt;</code>, treating it as its
2084 fundamental data structure, without mandating a specific type list
2085 representation;</p>
2086 </li>
2087 <li>
2088 <p>uses template aliases as its metafunctions, with the expression <code>F&lt;T...&gt;</code>
2089 serving as the equivalent of a function call;</p>
2090 </li>
2091 <li>
2092 <p>exploits the structural similarity between the data structure <code>L&lt;T...&gt;</code>
2093 and the metafunction call <code>F&lt;T...&gt;</code>;</p>
2094 </li>
2095 <li>
2096 <p>leverages parameter pack expansion as much as possible, instead of using the
2097 traditional recursive implementations;</p>
2098 </li>
2099 <li>
2100 <p>relies on inline definitions of template aliases for function composition,
2101 instead of providing library support for this task.</p>
2102 </li>
2103 </ul>
2104 </div>
2105 </div>
2106 </div>
2107 <div class="sect1">
2108 <h2 id="further_reading">Further reading</h2>
2109 <div class="sectionbody">
2110 <div class="paragraph">
2111 <p><a href="simple_cxx11_metaprogramming_2.html">Part 2 is now available</a>, in which I
2112 show algorithms that allow us to treat type lists as sets, maps, and vectors,
2113 and demonstrate various C&#43;&#43;11 implementation techniques in the process.</p>
2114 </div>
2115 </div>
2116 </div>
2117 </div>
2118 <div id="footer">
2119 <div id="footer-text">
2120 Last updated 2019-12-10 00:19:27 UTC
2121 </div>
2122 </div>
2123 <style>
2124
2125 *:not(pre)>code { background: none; color: #600000; }
2126 /* table tr.even, table tr.alt, table tr:nth-of-type(even) { background: none; } */
2127
2128 </style>
2129 </body>
2130 </html>