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++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">
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"}
33 sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
37 svg:not(:root){overflow:hidden}
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}
64 img,object,svg{display:inline-block;vertical-align:middle}
65 textarea{height:auto;min-height:50px}
67 .center{margin-left:auto;margin-right:auto}
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}
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}
79 h2{font-size:1.6875em}
80 h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
81 h4,h5{font-size:1.125em}
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}
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}
344 .aqua-background{background-color:#00fafa}
346 .black-background{background-color:#000}
348 .blue-background{background-color:#0000fa}
349 .fuchsia{color:#bf00bf}
350 .fuchsia-background{background-color:#fa00fa}
352 .gray-background{background-color:#7d7d7d}
353 .green{color:#006000}
354 .green-background{background-color:#007d00}
356 .lime-background{background-color:#00fa00}
357 .maroon{color:#600000}
358 .maroon-background{background-color:#7d0000}
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}
366 .red-background{background-color:#fa0000}
367 .silver{color:#909090}
368 .silver-background{background-color:#bcbcbc}
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}
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}
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}}
434 <body class="article toc2 toc-left">
436 <h1>Simple C++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>
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++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>
458 <div class="sectionbody">
459 <div class="paragraph lead">
460 <p><em>With variadic templates, parameter packs and template aliases</em></p>
462 <div class="admonitionblock note">
466 <div class="title">Note</div>
469 I was motivated to write this after I read Eric Niebler’s
471 <a href="http://ericniebler.com/2014/11/13/tiny-metaprogramming-library/">Tiny
472 Metaprogramming Library</a> article. Thanks Eric.
480 <h2 id="c11_changes_the_playing_field">C++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++
484 metaprogramming seem a solved problem. Perhaps MPL wasn’t ideal, but it was
485 good enough to the point that there wasn’t really a need to seek or produce
488 <div class="paragraph">
489 <p>C++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++11, type lists are
495 <div class="listingblock">
496 <div class="content">
497 <pre class="highlight"><code>// C++11
498 template<class... T> struct type_list {};</code></pre>
501 <div class="paragraph">
502 <p>and there is hardly a reason to use anything else.</p>
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>
508 <div class="listingblock">
509 <div class="content">
510 <pre class="highlight"><code>// C++03
511 template<class T> struct add_pointer { typedef T* type; };</code></pre>
514 <div class="paragraph">
515 <p>and were used in the following manner:</p>
517 <div class="listingblock">
518 <div class="content">
519 <pre class="highlight"><code>// C++03
520 typedef typename add_pointer<X>::type Xp;</code></pre>
523 <div class="paragraph">
524 <p>In C++11, metafunctions can be template aliases, instead of class templates:</p>
526 <div class="listingblock">
527 <div class="content">
528 <pre class="highlight"><code>// C++11
529 template<class T> using add_pointer = T*;</code></pre>
532 <div class="paragraph">
533 <p>The above example use then becomes</p>
535 <div class="listingblock">
536 <div class="content">
537 <pre class="highlight"><code>// C++11
538 typedef add_pointer<X> Xp;</code></pre>
541 <div class="paragraph">
542 <p>or, if you prefer to be seen as C++11-savvy,</p>
544 <div class="listingblock">
545 <div class="content">
546 <pre class="highlight"><code>// C++11
547 using Xp = add_pointer<X>;</code></pre>
550 <div class="paragraph">
551 <p>This is a considerable improvement in more complex expressions:</p>
553 <div class="listingblock">
554 <div class="content">
555 <pre class="highlight"><code>// C++03
557 typename add_reference<
558 typename add_const<
559 typename add_pointer<X>::type
561 >::type Xpcr;</code></pre>
564 <div class="listingblock">
565 <div class="content">
566 <pre class="highlight"><code>// C++11
567 using Xpcr = add_reference<add_const<add_pointer<X>>>;</code></pre>
570 <div class="paragraph">
571 <p>(The example also takes advantage of another C++11 feature - you can now use
572 <code>>></code> to close templates without it being interpreted as a right shift.)</p>
574 <div class="paragraph">
575 <p>In addition, template aliases can be passed to template template parameters:</p>
577 <div class="listingblock">
578 <div class="content">
579 <pre class="highlight"><code>// C++11
580 template<template<class... T> class F> struct X
584 X<add_pointer>; // works!</code></pre>
587 <div class="paragraph">
588 <p>These language improvements allow for C++11 metaprogramming that is
589 substantially different than its idiomatic C++03 equivalent. Boost.MPL is no
590 longer good enough, and <em>something must be done</em>. But what?</p>
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’s start with the basics. Our basic data structure will be the type list:</p>
600 <div class="listingblock">
601 <div class="content">
602 <pre class="highlight"><code>template<class... T> struct mp_list {};</code></pre>
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>
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>
615 <div class="paragraph">
616 <p>So we have our type list and can put things into it:</p>
618 <div class="listingblock">
619 <div class="content">
620 <pre class="highlight"><code>using list = mp_list<int, char, float, double, void>;</code></pre>
623 <div class="paragraph">
624 <p>but can’t do anything else with it yet. We’ll need a library of primitives that
625 operate on <code>mp_list</code>s. But before we get into that, let’s consider another
626 interesting question first.</p>
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<int, float, void*></code>, or
632 <code><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4115.html">std::packer</a><int,
633 float, void*></code>.</p>
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<int*, float*, void**></code> in the first
639 case and <code>std::packer<int*, float*, void**></code> in the second.</p>
641 <div class="paragraph">
642 <p>To do that, we need to first convert <code>std::tuple<int, float, void*></code> to
643 <code>mp_list<int, float, void*></code>, apply <code>add_pointer</code> to each element obtaining
644 <code>mp_list<int*, float*, void**></code>, then convert that back to <code>std::tuple</code>.</p>
646 <div class="paragraph">
647 <p>These conversion steps are a quite common occurrence, and we’ll write a
648 primitive that helps us perform them, called <code>mp_rename</code>. We want</p>
650 <div class="listingblock">
651 <div class="content">
652 <pre class="highlight"><code>mp_rename<std::tuple<int, float, void*>, mp_list></code></pre>
655 <div class="paragraph">
658 <div class="listingblock">
659 <div class="content">
660 <pre class="highlight"><code>mp_list<int, float, void*></code></pre>
663 <div class="paragraph">
664 <p>and conversely,</p>
666 <div class="listingblock">
667 <div class="content">
668 <pre class="highlight"><code>mp_rename<mp_list<int, float, void*>, std::tuple></code></pre>
671 <div class="paragraph">
674 <div class="listingblock">
675 <div class="content">
676 <pre class="highlight"><code>std::tuple<int, float, void*></code></pre>
679 <div class="paragraph">
680 <p>Here is the implementation of <code>mp_rename</code>:</p>
682 <div class="listingblock">
683 <div class="content">
684 <pre class="highlight"><code>template<class A, template<class...> class B> struct mp_rename_impl;
686 template<template<class...> class A, class... T, template<class...> class B>
687 struct mp_rename_impl<A<T...>, B>
689 using type = B<T...>;
692 template<class A, template<class...> class B>
693 using mp_rename = typename mp_rename_impl<A, B>::type;</code></pre>
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
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>
707 <div class="paragraph">
708 <p>In fact, it can even rename non-variadic class templates, as in the following
711 <div class="listingblock">
712 <div class="content">
713 <pre class="highlight"><code>mp_rename<std::pair<int, float>, std::tuple> // -> std::tuple<int, float>
714 mp_rename<mp_list<int, float>, std::pair> // -> std::pair<int, float>
715 mp_rename<std::shared_ptr<int>, std::unique_ptr> // -> std::unique_ptr<int></code></pre>
718 <div class="paragraph">
719 <p>There is a limit to the magic; <code>unique_ptr</code> can’t be renamed to <code>shared_ptr</code>:</p>
721 <div class="listingblock">
722 <div class="content">
723 <pre class="highlight"><code>mp_rename<std::unique_ptr<int>, std::shared_ptr> // error</code></pre>
726 <div class="paragraph">
727 <p>because <code>unique_ptr<int></code> is actually <code>unique_ptr<int,
728 std::default_delete<int>></code> and <code>mp_rename</code> renames it to <code>shared_ptr<int,
729 std::default_delete<int>></code>, which doesn’t compile. But it still works in many
730 more cases than one would naively expect at first.</p>
732 <div class="paragraph">
733 <p>With conversions no longer a problem, let’s move on to primitives and define a
734 simple one, <code>mp_size</code>, for practice. We want <code>mp_size<mp_list<T...>></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>
738 <div class="listingblock">
739 <div class="content">
740 <pre class="highlight"><code>template<class L> struct mp_size_impl;
742 template<class... T> struct mp_size_impl<mp_list<T...>>
744 using type = std::integral_constant<std::size_t, sizeof...(T)>;
747 template<class L> using mp_size = typename mp_size_impl<L>::type;</code></pre>
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>
754 <div class="paragraph">
755 <p><code>std::integral_constant</code> is a standard C++11 type that wraps an integral
756 constant (that is, a compile-time constant integer value) into a type.</p>
758 <div class="paragraph">
759 <p>Since metaprogramming operates on type lists, which can only hold types, it’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<L>::value</code> to retrieve it.</p>
766 <div class="paragraph">
767 <p>We now have our <code>mp_size</code>, but you may have noticed that there’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>
771 <div class="listingblock">
772 <div class="content">
773 <pre class="highlight"><code>template<class... T> struct mp_size_impl<mp_list<T...>></code></pre>
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>
780 <div class="listingblock">
781 <div class="content">
782 <pre class="highlight"><code>template<class L> struct mp_size_impl;
784 template<template<class...> class L, class... T> struct mp_size_impl<L<T...>>
786 using type = std::integral_constant<std::size_t, sizeof...(T)>;
789 template<class L> using mp_size = typename mp_size_impl<L>::type;</code></pre>
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
797 <div class="paragraph">
798 <p>This is nice. It is so nice that I’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>
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>
808 <div class="paragraph">
809 <p>To illustrate it, let me introduce the primitive <code>mp_length</code>. It’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>
814 <div class="listingblock">
815 <div class="content">
816 <pre class="highlight"><code>template<class... T> using mp_length =
817 std::integral_constant<std::size_t, sizeof...(T)>;</code></pre>
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>
824 <div class="listingblock">
825 <div class="content">
826 <pre class="highlight"><code>template<template<class...> class L, class... T> struct mp_size_impl<L<T...>>
828 using type = mp_length<T...>;
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>
836 <div class="listingblock">
837 <div class="content">
838 <pre class="highlight"><code><strong>mp_list</strong><int, void, float></code></pre>
841 <div class="paragraph">
844 <div class="listingblock">
845 <div class="content">
846 <pre class="highlight"><code><strong>mp_length</strong><int, void, float></code></pre>
849 <div class="paragraph">
850 <p>Do we already have a primitive that does a similar thing?</p>
852 <div class="paragraph">
853 <p>(Not much of a choice, is there?)</p>
855 <div class="paragraph">
856 <p>Indeed we have, and it’s called <code>mp_rename</code>.</p>
858 <div class="listingblock">
859 <div class="content">
860 <pre class="highlight"><code>template<class L> using mp_size = mp_rename<L, mp_length>;</code></pre>
863 <div class="paragraph">
864 <p>I don’t know about you, but I find this technique fascinating. It exploits the
865 structural similarity between a list, <code>L<T...></code>, and a metafunction "call",
866 <code>F<T...></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>
870 <div class="paragraph">
871 <p>(Other metaprogramming libraries provide a dedicated <code>apply</code> primitive for
872 this job. <code>apply<F, L></code> calls the metafunction <code>F</code> with the contents of the
873 list <code>L</code>. We’ll add an alias <code>mp_apply<F, L></code> that calls <code>mp_rename<L, F></code> for
876 <div class="listingblock">
877 <div class="content">
878 <pre class="highlight"><code>template<template<class...> class F, class L> using mp_apply = mp_rename<L, F>;</code></pre>
884 <h2 id="mp_transform">mp_transform</h2>
885 <div class="sectionbody">
886 <div class="paragraph">
887 <p>Let’s revisit the example I gave earlier - someone hands us <code>std::tuple<X, Y,
888 Z></code> and we need to compute <code>std::tuple<X*, Y*, Z*></code>. We already have
889 <code>add_pointer</code>:</p>
891 <div class="listingblock">
892 <div class="content">
893 <pre class="highlight"><code>template<class T> using add_pointer = T*;</code></pre>
896 <div class="paragraph">
897 <p>so we just need to apply it to each element of the input tuple.</p>
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’ll use <code>transform</code>, for consistency with the established C++
903 practice (<code>map</code> is a data structure in both the STL and Boost.MPL.)</p>
905 <div class="paragraph">
906 <p>We’ll call our algorithm <code>mp_transform</code>, and <code>mp_transform<F, L></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>
911 <div class="paragraph">
912 <p>There are many ways to implement <code>mp_transform</code>; the one we’ll pick will make
913 use of another primitive, <code>mp_push_front</code>. <code>mp_push_front<L, T></code>, as its name
914 implies, adds <code>T</code> as a first element in <code>L</code>:</p>
916 <div class="listingblock">
917 <div class="content">
918 <pre class="highlight"><code>template<class L, class T> struct mp_push_front_impl;
920 template<template<class...> class L, class... U, class T>
921 struct mp_push_front_impl<L<U...>, T>
923 using type = L<T, U...>;
926 template<class L, class T>
927 using mp_push_front = typename mp_push_front_impl<L, T>::type;</code></pre>
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++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>
936 <div class="listingblock">
937 <div class="content">
938 <pre class="highlight"><code>template<class L, class... T> struct mp_push_front_impl;
940 template<template<class...> class L, class... U, class... T>
941 struct mp_push_front_impl<L<U...>, T...>
943 using type = L<T..., U...>;
946 template<class L, class... T>
947 using mp_push_front = typename mp_push_front_impl<L, T...>::type;</code></pre>
950 <div class="paragraph">
951 <p>On to <code>mp_transform</code>:</p>
953 <div class="listingblock">
954 <div class="content">
955 <pre class="highlight"><code>template<template<class...> class F, class L> struct mp_transform_impl;
957 template<template<class...> class F, class L>
958 using mp_transform = typename mp_transform_impl<F, L>::type;
960 template<template<class...> class F, template<class...> class L>
961 struct mp_transform_impl<F, L<>>
963 using type = L<>;
966 template<template<class...> class F, template<class...> class L, class T1, class... T>
967 struct mp_transform_impl<F, L<T1, T...>>
969 using _first = F<T1>;
970 using _rest = mp_transform<F, L<T...>>;
972 using type = mp_push_front<_rest, _first>;
976 <div class="paragraph">
977 <p>This is a straightforward recursive implementation that should be familiar to
978 people with functional programming background.</p>
980 <div class="paragraph">
981 <p>Can we do better? It turns out that in C++11, we can.</p>
983 <div class="listingblock">
984 <div class="content">
985 <pre class="highlight"><code>template<template<class...> class F, class L> struct mp_transform_impl;
987 template<template<class...> class F, class L>
988 using mp_transform = typename mp_transform_impl<F, L>::type;
990 template<template<class...> class F, template<class...> class L, class... T>
991 struct mp_transform_impl<F, L<T...>>
993 using type = L<F<T>...>;
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<T>...</code> part does all the iteration work for us.</p>
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>
1005 <div class="listingblock">
1006 <div class="content">
1007 <pre class="highlight"><code>using input = std::tuple<int, void, float>;
1008 using expected = std::tuple<int*, void*, float*>;
1010 using result = mp_transform<add_pointer, input>;
1012 static_assert( std::is_same<result, expected>::value, "" );</code></pre>
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>
1024 <div class="listingblock">
1025 <div class="content">
1026 <pre class="highlight"><code>using input = std::pair<std::tuple<X1, X2, X3>, std::tuple<Y1, Y2, Y3>>;</code></pre>
1029 <div class="paragraph">
1030 <p>we had to produce</p>
1032 <div class="listingblock">
1033 <div class="content">
1034 <pre class="highlight"><code>using expected = std::tuple<std::pair<X1, Y1>, std::pair<X2, Y2>, std::pair<X3, Y3>>;</code></pre>
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>
1043 <div class="paragraph">
1044 <p>Changing our unary transform algorithm into a binary one isn’t hard:</p>
1046 <div class="listingblock">
1047 <div class="content">
1048 <pre class="highlight"><code>template<template<class...> class F, class L1, class L2>
1049 struct mp_transform2_impl;
1051 template<template<class...> class F, class L1, class L2>
1052 using mp_transform2 = typename mp_transform2_impl<F, L1, L2>::type;
1054 template<template<class...> class F,
1055 template<class...> class L1, class... T1,
1056 template<class...> class L2, class... T2>
1057 struct mp_transform2_impl<F, L1<T1...>, L2<T2...>>
1059 static_assert( sizeof...(T1) == sizeof...(T2),
1060 "The arguments of mp_transform2 should be of the same size" );
1062 using type = L1<F<T1,T2>...>;
1066 <div class="paragraph">
1067 <p>and we can now do</p>
1069 <div class="listingblock">
1070 <div class="content">
1071 <pre class="highlight"><code>using input = std::pair<std::tuple<X1, X2, X3>, std::tuple<Y1, Y2, Y3>>;
1072 using expected = std::tuple<std::pair<X1, Y1>, std::pair<X2, Y2>, std::pair<X3, Y3>>;
1074 using result = mp_transform2<std::pair, input::first_type, input::second_type>;
1076 static_assert( std::is_same<result, expected>::value, "" );</code></pre>
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>
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>
1090 <div class="listingblock">
1091 <div class="content">
1092 <pre class="highlight"><code>template<template<class...> class F, class... L> struct mp_transform_impl;
1094 template<template<class...> class F, class... L>
1095 using mp_transform = typename mp_transform_impl<F, L...>::type;</code></pre>
1098 <div class="paragraph">
1099 <p>and then add the unary and binary specializations:</p>
1101 <div class="listingblock">
1102 <div class="content">
1103 <pre class="highlight"><code>template<template<class...> class F, template<class...> class L, class... T>
1104 struct mp_transform_impl<F, L<T...>>
1106 using type = L<F<T>...>;
1109 template<template<class...> class F,
1110 template<class...> class L1, class... T1,
1111 template<class...> class L2, class... T2>
1112 struct mp_transform_impl<F, L1<T1...>, L2<T2...>>
1114 static_assert( sizeof...(T1) == sizeof...(T2),
1115 "The arguments of mp_transform should be of the same size" );
1117 using type = L1<F<T1,T2>...>;
1121 <div class="paragraph">
1122 <p>We can also add ternary and further specializations.</p>
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’ll show one
1127 possible abridged implementation here for completeness:</p>
1129 <div class="listingblock">
1130 <div class="content">
1131 <pre class="highlight"><code>template<template<class...> class F, class E, class... L>
1132 struct mp_transform_impl;
1134 template<template<class...> class F, class... L>
1135 using mp_transform = typename mp_transform_impl<F, mp_empty<L...>, L...>::type;
1137 template<template<class...> class F, class L1, class... L>
1138 struct mp_transform_impl<F, mp_true, L1, L...>
1140 using type = mp_clear<L1>;
1143 template<template<class...> class F, class... L>
1144 struct mp_transform_impl<F, mp_false, L...>
1146 using _first = F< typename mp_front_impl<L>::type... >;
1147 using _rest = mp_transform< F, typename mp_pop_front_impl<L>::type... >;
1149 using type = mp_push_front<_rest, _first>;
1153 <div class="paragraph">
1154 <p>but will omit the primitives that it uses. These are</p>
1159 <p><code>mp_true</code> — an alias for <code>std::integral_constant<bool, true></code>.</p>
1162 <p><code>mp_false</code> — an alias for <code>std::integral_constant<bool, false></code>.</p>
1165 <p><code>mp_empty<L...></code> — returns <code>mp_true</code> if all lists are empty, <code>mp_false</code>
1169 <p><code>mp_clear<L></code> — returns an empty list of the same type as <code>L</code>.</p>
1172 <p><code>mp_front<L></code> — returns the first element of <code>L</code>.</p>
1175 <p><code>mp_pop_front<L></code> — returns <code>L</code> without its first element.</p>
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<add_pointer,
1182 std::pair<int, float>></code> works with the <code>F<T>...</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>
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’s solution:</p>
1200 <div class="listingblock">
1201 <div class="content">
1202 <pre class="highlight"><code>namespace detail
1204 template<typename Ret, typename...Is, typename ...Ks,
1206 Ret tuple_cat_(typelist<Is...>, typelist<Ks...>,
1209 return Ret{std::get<Ks::value>(
1210 std::get<Is::value>(tpls))...};
1214 template<typename...Tuples,
1216 typelist_apply_t<
1217 meta_quote<std::tuple>,
1218 typelist_cat_t<typelist<as_typelist_t<Tuples>...> > > >
1219 Res tuple_cat(Tuples &&... tpls)
1221 static constexpr std::size_t N = sizeof...(Tuples);
1222 // E.g. [0,0,0,2,2,2,3,3]
1225 typelist_transform_t<
1226 typelist<as_typelist_t<Tuples>...>,
1227 typelist_transform_t<
1228 as_typelist_t<make_index_sequence<N> >,
1229 meta_quote<meta_always> >,
1230 meta_quote<typelist_transform_t> > >;
1231 // E.g. [0,1,2,0,1,2,0,1]
1234 typelist_transform_t<
1235 typelist<as_typelist_t<Tuples>...>,
1237 meta_quote<as_typelist_t>,
1238 meta_quote_i<std::size_t, make_index_sequence>,
1239 meta_quote<typelist_size_t> > > >;
1240 return detail::tuple_cat_<Res>(
1243 std::forward_as_tuple(std::forward<Tuples>(tpls)...));
1247 <div class="paragraph">
1248 <p>All right, challenge accepted. Let’s see what we can do.</p>
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>
1256 <div class="paragraph">
1257 <p>So, for example, if tuple_cat is invoked as</p>
1259 <div class="listingblock">
1260 <div class="content">
1261 <pre class="highlight"><code>std::tuple<int, short, long> t1;
1262 std::tuple<> t2;
1263 std::tuple<float, double, long double> t3;
1264 std::tuple<void*, char*> t4;
1266 auto res = tuple_cat(t1, t2, t3, t4);</code></pre>
1269 <div class="paragraph">
1270 <p>we’ll create the tuple</p>
1272 <div class="listingblock">
1273 <div class="content">
1274 <pre class="highlight"><code>std::tuple<std::tuple<int, short, long>, std::tuple<>,
1275 std::tuple<float, double, long double>, std::tuple<void*, char*>> t{t1, t2, t3, t4};</code></pre>
1278 <div class="paragraph">
1279 <p>and then extract the elements of t via</p>
1281 <div class="listingblock">
1282 <div class="content">
1283 <pre class="highlight"><code>std::get<0>(std::get<0>(t)), // t1[0]
1284 std::get<1>(std::get<0>(t)), // t1[1]
1285 std::get<2>(std::get<0>(t)), // t1[2]
1286 std::get<0>(std::get<2>(t)), // t3[0]
1287 std::get<1>(std::get<2>(t)), // t3[1]
1288 std::get<2>(std::get<2>(t)), // t3[2]
1289 std::get<0>(std::get<3>(t)), // t4[0]
1290 std::get<1>(std::get<3>(t)), // t4[1]</code></pre>
1293 <div class="paragraph">
1294 <p>(<code>t2</code> is empty, so we take nothing from it.)</p>
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’s deal with the
1299 return type of <code>tuple_cat</code>.</p>
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
1305 <a href="https://ericniebler.github.io/meta/group__transformation.html"><code>meta::concat</code></a>
1306 in Eric Niebler’s <a href="https://github.com/ericniebler/meta">Meta</a> library, but I’ll
1307 call it <code>mp_append</code>, after its classic Lisp name.</p>
1309 <div class="paragraph">
1310 <p>(Lisp is today’s equivalent of Latin. Educated people are supposed to have
1311 studied and forgotten it.)</p>
1313 <div class="listingblock">
1314 <div class="content">
1315 <pre class="highlight"><code>template<class... L> struct mp_append_impl;
1317 template<class... L> using mp_append = typename mp_append_impl<L...>::type;
1319 template<> struct mp_append_impl<>
1321 using type = mp_list<>;
1324 template<template<class...> class L, class... T> struct mp_append_impl<L<T...>>
1326 using type = L<T...>;
1329 template<template<class...> class L1, class... T1,
1330 template<class...> class L2, class... T2, class... Lr>
1331 struct mp_append_impl<L1<T1...>, L2<T2...>, Lr...>
1333 using type = mp_append<L1<T1..., T2...>, Lr...>;
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++11.</p>
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’ve arbitrarily chosen to return an empty
1346 <code>mp_list</code>.</p>
1348 <div class="paragraph">
1349 <p>We’re now ready with the declaration of <code>tuple_cat</code>:</p>
1351 <div class="listingblock">
1352 <div class="content">
1353 <pre class="highlight"><code>template<class... Tp,
1354 class R = mp_append<typename std::remove_reference<Tp>::type...>>
1355 R tuple_cat( Tp &&... tp );</code></pre>
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 — <code>std::tuple<int, short, long>&</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>
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<></code> in that
1368 case, but the correct result is <code>std::tuple<></code>.</p>
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’ll try to append more elements to <code>std::pair</code>, and it will fail.</p>
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>
1378 <div class="listingblock">
1379 <div class="content">
1380 <pre class="highlight"><code>template<class... Tp,
1381 class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
1382 R tuple_cat( Tp &&... tp );</code></pre>
1385 <div class="paragraph">
1386 <p>With the return type taken care of, let’s now move on to computing inner. We
1389 <div class="listingblock">
1390 <div class="content">
1391 <pre class="highlight"><code>[x1, x2, x3], [], [y1, y2, y3], [z1, z2]</code></pre>
1394 <div class="paragraph">
1395 <p>as input and we need to output</p>
1397 <div class="listingblock">
1398 <div class="content">
1399 <pre class="highlight"><code>[0, 0, 0, 2, 2, 2, 3, 3]</code></pre>
1402 <div class="paragraph">
1403 <p>which is the concatenation of</p>
1405 <div class="listingblock">
1406 <div class="content">
1407 <pre class="highlight"><code>[0, 0, 0], [], [2, 2, 2], [3, 3]</code></pre>
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>
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>
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>
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>
1430 <div class="paragraph">
1431 <p>We’ll call this function <code>mp_fill</code>, after <code>std::fill</code>.</p>
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’s an
1436 implementation along these lines:</p>
1438 <div class="listingblock">
1439 <div class="content">
1440 <pre class="highlight"><code>template<class V> struct mp_constant
1442 template<class...> using apply = V;
1445 template<class L, class V>
1446 using mp_fill = mp_transform<mp_constant<V>::template apply, L>;</code></pre>
1449 <div class="paragraph">
1450 <p>Here’s an alternate implementation:</p>
1452 <div class="listingblock">
1453 <div class="content">
1454 <pre class="highlight"><code>template<class L, class V> struct mp_fill_impl;
1456 template<template<class...> class L, class... T, class V>
1457 struct mp_fill_impl<L<T...>, V>
1459 template<class...> using _fv = V;
1460 using type = L<_fv<T>...>;
1463 template<class L, class V> using mp_fill = typename mp_fill_impl<L, V>::type;</code></pre>
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>
1472 <div class="paragraph">
1473 <p>Most C++11 programmers will probably find the second implementation easier to
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++14 already has a standard way of generating an index
1482 <a href="http://en.cppreference.com/w/cpp/utility/integer_sequence"><code>std::make_index_sequence</code></a>.
1483 Since Eric’s original solution makes use of <code>make_index_sequence</code>, let’s follow
1486 <div class="paragraph">
1487 <p>Technically, this takes us outside of C++11, but <code>make_index_sequence</code> is not
1488 hard to implement (if efficiency is not a concern):</p>
1490 <div class="listingblock">
1491 <div class="content">
1492 <pre class="highlight"><code>template<class T, T... Ints> struct integer_sequence
1496 template<class S> struct next_integer_sequence;
1498 template<class T, T... Ints> struct next_integer_sequence<integer_sequence<T, Ints...>>
1500 using type = integer_sequence<T, Ints..., sizeof...(Ints)>;
1503 template<class T, T I, T N> struct make_int_seq_impl;
1505 template<class T, T N>
1506 using make_integer_sequence = typename make_int_seq_impl<T, 0, N>::type;
1508 template<class T, T I, T N> struct make_int_seq_impl
1510 using type = typename next_integer_sequence<
1511 typename make_int_seq_impl<T, I+1, N>::type>::type;
1514 template<class T, T N> struct make_int_seq_impl<T, N, N>
1516 using type = integer_sequence<T>;
1519 template<std::size_t... Ints>
1520 using index_sequence = integer_sequence<std::size_t, Ints...>;
1522 template<std::size_t N>
1523 using make_index_sequence = make_integer_sequence<std::size_t, N>;</code></pre>
1526 <div class="paragraph">
1527 <p>We can now obtain an <code>index_sequence<0, 1, 2, 3></code>:</p>
1529 <div class="listingblock">
1530 <div class="content">
1531 <pre class="highlight"><code>template<class... Tp,
1532 class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
1533 R tuple_cat( Tp &&... tp )
1535 std::size_t const N = sizeof...(Tp);
1539 using seq = make_index_sequence<N>;
1543 <div class="paragraph">
1544 <p>but <code>make_index_sequence<4></code> returns <code>integer_sequence<std::size_t, 0, 1, 2,
1545 3></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’ll introduce a function <code>mp_from_sequence</code> that does
1549 <div class="listingblock">
1550 <div class="content">
1551 <pre class="highlight"><code>template<class S> struct mp_from_sequence_impl;
1553 template<template<class T, T... I> class S, class U, U... J>
1554 struct mp_from_sequence_impl<S<U, J...>>
1556 using type = mp_list<std::integral_constant<U, J>...>;
1559 template<class S> using mp_from_sequence = typename mp_from_sequence_impl<S>::type;</code></pre>
1562 <div class="paragraph">
1563 <p>We can now compute the two lists that we wanted to transform with <code>mp_fill</code>:</p>
1565 <div class="listingblock">
1566 <div class="content">
1567 <pre class="highlight"><code>template<class... Tp,
1568 class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
1569 R tuple_cat( Tp &&... tp )
1571 std::size_t const N = sizeof...(Tp);
1575 using list1 = mp_list<typename std::remove_reference<Tp>::type...>;
1576 using list2 = mp_from_sequence<make_index_sequence<N>>;
1578 // list1: [[x1, x2, x3], [], [y1, y2, y3], [z1, z2]]
1579 // list2: [0, 1, 2, 3]
1585 <div class="paragraph">
1586 <p>and finish the job of computing <code>inner</code>:</p>
1588 <div class="listingblock">
1589 <div class="content">
1590 <pre class="highlight"><code>template<class... Tp,
1591 class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
1592 R tuple_cat( Tp &&... tp )
1594 std::size_t const N = sizeof...(Tp);
1598 using list1 = mp_list<typename std::remove_reference<Tp>::type...>;
1599 using list2 = mp_from_sequence<make_index_sequence<N>>;
1601 // list1: [[x1, x2, x3], [], [y1, y2, y3], [z1, z2]]
1602 // list2: [0, 1, 2, 3]
1604 using list3 = mp_transform<mp_fill, list1, list2>;
1606 // list3: [[0, 0, 0], [], [2, 2, 2], [3, 3]]
1608 using inner = mp_rename<list3, mp_append>; // or mp_apply<mp_append, list3>
1610 // inner: [0, 0, 0, 2, 2, 2, 3, 3]
1616 <div class="paragraph">
1617 <p>For <code>outer</code>, we again have</p>
1619 <div class="listingblock">
1620 <div class="content">
1621 <pre class="highlight"><code>[x1, x2, x3], [], [y1, y2, y3], [z1, z2]</code></pre>
1624 <div class="paragraph">
1625 <p>as input and we need to output</p>
1627 <div class="listingblock">
1628 <div class="content">
1629 <pre class="highlight"><code>[0, 1, 2, 0, 1, 2, 0, 1]</code></pre>
1632 <div class="paragraph">
1633 <p>which is the concatenation of</p>
1635 <div class="listingblock">
1636 <div class="content">
1637 <pre class="highlight"><code>[0, 1, 2], [], [0, 1, 2], [0, 1]</code></pre>
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<N></code>, where <code>N</code> is the number of elements.</p>
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>
1649 <div class="listingblock">
1650 <div class="content">
1651 <pre class="highlight"><code>template<class N> using mp_iota = mp_from_sequence<make_index_sequence<N::value>>;
1653 template<class L> using F = mp_iota<mp_size<L>>;
1655 template<class... Tp,
1656 class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
1657 R tuple_cat( Tp &&... tp )
1659 std::size_t const N = sizeof...(Tp);
1663 using list1 = mp_list<typename std::remove_reference<Tp>::type...>;
1664 using list2 = mp_transform<F, list1>;
1666 // list2: [[0, 1, 2], [], [0, 1, 2], [0, 1]]
1668 using outer = mp_rename<list2, mp_append>;
1670 // outer: [0, 1, 2, 0, 1, 2, 0, 1]
1676 <div class="paragraph">
1677 <p>Well that was easy. Surprisingly easy. The one small annoyance is that we can’t
1678 define <code>F</code> inside <code>tuple_cat</code> - templates can’t be defined in functions.</p>
1680 <div class="paragraph">
1681 <p>Let’s put everything together.</p>
1683 <div class="listingblock">
1684 <div class="content">
1685 <pre class="highlight"><code>template<class N> using mp_iota = mp_from_sequence<make_index_sequence<N::value>>;
1687 template<class L> using F = mp_iota<mp_size<L>>;
1689 template<class R, class...Is, class... Ks, class Tp>
1690 R tuple_cat_( mp_list<Is...>, mp_list<Ks...>, Tp tp )
1692 return R{ std::get<Ks::value>(std::get<Is::value>(tp))... };
1695 template<class... Tp,
1696 class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
1697 R tuple_cat( Tp &&... tp )
1699 std::size_t const N = sizeof...(Tp);
1703 using list1 = mp_list<typename std::remove_reference<Tp>::type...>;
1704 using list2 = mp_from_sequence<make_index_sequence<N>>;
1706 // list1: [[x1, x2, x3], [], [y1, y2, y3], [z1, z2]]
1707 // list2: [0, 1, 2, 3]
1709 using list3 = mp_transform<mp_fill, list1, list2>;
1711 // list3: [[0, 0, 0], [], [2, 2, 2], [3, 3]]
1713 using inner = mp_rename<list3, mp_append>; // or mp_apply<mp_append, list3>
1715 // inner: [0, 0, 0, 2, 2, 2, 3, 3]
1719 using list4 = mp_transform<F, list1>;
1721 // list4: [[0, 1, 2], [], [0, 1, 2], [0, 1]]
1723 using outer = mp_rename<list4, mp_append>;
1725 // outer: [0, 1, 2, 0, 1, 2, 0, 1]
1727 return tuple_cat_<R>( inner(), outer(),
1728 std::forward_as_tuple( std::forward<Tp>(tp)... ) );
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>
1737 <div class="listingblock">
1738 <div class="content">
1739 <pre class="highlight"><code>return tuple_cat_<R>( mp_rename<inner, mp_list>(), outer(),
1740 std::forward_as_tuple( std::forward<Tp>(tp)... ) );</code></pre>
1743 <div class="paragraph">
1744 <p>Let’s define a <code>print_tuple</code> function and see if everything checks out.</p>
1746 <div class="listingblock">
1747 <div class="content">
1748 <pre class="highlight"><code>template<int I, int N, class... T> struct print_tuple_
1750 void operator()( std::tuple<T...> const & tp ) const
1752 using Tp = typename std::tuple_element<I, std::tuple<T...>>::type;
1754 print_type<Tp>( " ", ": " );
1756 std::cout << std::get<I>( tp ) << ";";
1758 print_tuple_< I+1, N, T... >()( tp );
1762 template<int N, class... T> struct print_tuple_<N, N, T...>
1764 void operator()( std::tuple<T...> const & ) const
1769 template<class... T> void print_tuple( std::tuple<T...> const & tp )
1771 std::cout << "{";
1772 print_tuple_<0, sizeof...(T), T...>()( tp );
1773 std::cout << " }\n";
1778 std::tuple<int, long> t1{ 1, 2 };
1779 std::tuple<> t2;
1780 std::tuple<float, double, long double> t3{ 3, 4, 5 };
1781 std::pair<void const*, char const*> t4{ "pv", "test" };
1783 using expected = std::tuple<int, long, float, double, long double,
1784 void const*, char const*>;
1786 auto result = ::tuple_cat( t1, t2, t3, t4 );
1788 static_assert( std::is_same<decltype(result), expected>::value, "" );
1790 print_tuple( result );
1794 <div class="paragraph">
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>
1803 <div class="paragraph">
1804 <p>Seems to work. But there’s at least one error left. To see why, replace the
1807 <div class="listingblock">
1808 <div class="content">
1809 <pre class="highlight"><code>std::tuple<int, long> t1{ 1, 2 };</code></pre>
1812 <div class="paragraph">
1815 <div class="listingblock">
1816 <div class="content">
1817 <pre class="highlight"><code>std::pair<int, long> t1{ 1, 2 };</code></pre>
1820 <div class="paragraph">
1821 <p>We now get an error at</p>
1823 <div class="listingblock">
1824 <div class="content">
1825 <pre class="highlight"><code>using inner = mp_rename<list3, mp_append>;</code></pre>
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>
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>
1837 <div class="listingblock">
1838 <div class="content">
1839 <pre class="highlight"><code>using inner = mp_rename<mp_push_front<list3, mp_list<>>, mp_append>;</code></pre>
1842 <div class="paragraph">
1843 <p>The second way is to just convert all inputs to mp_list:</p>
1845 <div class="listingblock">
1846 <div class="content">
1847 <pre class="highlight"><code>using list1 = mp_list<
1848 mp_rename<typename std::remove_reference<Tp>::type, mp_list>...>;</code></pre>
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>
1855 <div class="paragraph">
1856 <p>We’re done. The results hopefully speak for themselves.</p>
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’re wondering why this article is called "Simple C++11
1865 metaprogramming", since what we covered so far wasn’t particularly simple.</p>
1867 <div class="paragraph">
1868 <p>The <em>relative</em> simplicity of our approach stems from the fact that we’ve not
1869 been doing any higher order metaprogramming, that is, we haven’t introduced any
1870 primitives that return metafunctions, such as <code>compose</code>, <code>bind</code>, or a lambda
1873 <div class="paragraph">
1874 <p>I posit that such higher order metaprogramming is, in the majority of cases,
1875 not necessary in C++11. Consider, for example, Eric Niebler’s solution given
1878 <div class="listingblock">
1879 <div class="content">
1880 <pre class="highlight"><code>using outer =
1882 typelist_transform_t<
1883 typelist<as_typelist_t<Tuples>...>,
1885 meta_quote<as_typelist_t>,
1886 meta_quote_i<std::size_t, make_index_sequence>,
1887 meta_quote<typelist_size_t> > > >;</code></pre>
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>
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++11 we can just do</p>
1900 <div class="listingblock">
1901 <div class="content">
1902 <pre class="highlight"><code>template<class... T> using Fgh = F<G<H<T...>>>;</code></pre>
1905 <div class="paragraph">
1906 <p>and that’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
1911 <div class="listingblock">
1912 <div class="content">
1913 <pre class="highlight"><code>template<class... T>
1914 using F = as_typelist_t<std::make_index_sequence<typelist_size_t<T...>::value>>;</code></pre>
1917 <div class="paragraph">
1918 <p>Similarly, if we need a metafunction that will return <code>sizeof(T) < sizeof(U)</code>,
1919 there is no need to enlist a metaprogramming lambda library as in</p>
1921 <div class="listingblock">
1922 <div class="content">
1923 <pre class="highlight"><code>lambda<_a, _b, less<sizeof_<_a>, sizeof_<_b>>>></code></pre>
1926 <div class="paragraph">
1927 <p>We could just define it inline:</p>
1929 <div class="listingblock">
1930 <div class="content">
1931 <pre class="highlight"><code>template<class T, class U> using sizeof_less = mp_bool<(sizeof(T) < sizeof(U))>;</code></pre>
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<L, V></code> returns the
1942 number of occurrences of the type <code>V</code> in the list <code>L</code>; <code>mp_count_if<L, P></code>
1943 counts the number of types in <code>L</code> for which <code>P<T></code> is <code>true</code>.</p>
1945 <div class="paragraph">
1946 <p>As a first step, I’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>
1949 <div class="listingblock">
1950 <div class="content">
1951 <pre class="highlight"><code>template<class... T> struct mp_plus_impl;
1953 template<class... T> using mp_plus = typename mp_plus_impl<T...>::type;
1955 template<> struct mp_plus_impl<>
1957 using type = std::integral_constant<int, 0>;
1960 template<class T1, class... T> struct mp_plus_impl<T1, T...>
1962 static constexpr auto _v = T1::value + mp_plus<T...>::value;
1964 using type = std::integral_constant<
1965 typename std::remove_const<decltype(_v)>::type, _v>;
1969 <div class="paragraph">
1970 <p>Now that we have <code>mp_plus</code>, <code>mp_count</code> is just</p>
1972 <div class="listingblock">
1973 <div class="content">
1974 <pre class="highlight"><code>template<class L, class V> struct mp_count_impl;
1976 template<template<class...> class L, class... T, class V>
1977 struct mp_count_impl<L<T...>, V>
1979 using type = mp_plus<std::is_same<T, V>...>;
1982 template<class L, class V> using mp_count = typename mp_count_impl<L, V>::type;</code></pre>
1985 <div class="paragraph">
1986 <p>This is another illustration of the power of parameter pack expansion. It’s a
1987 pity that we can’t use pack expansion in <code>mp_plus</code> as well, to obtain</p>
1989 <div class="listingblock">
1990 <div class="content">
1991 <pre class="highlight"><code>T1::value + T2::value + T3::value + T4::value + ...</code></pre>
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++17, it will be.</p>
1998 <div class="paragraph">
1999 <p><code>mp_count_if</code> is similarly straightforward:</p>
2001 <div class="listingblock">
2002 <div class="content">
2003 <pre class="highlight"><code>template<class L, template<class...> class P> struct mp_count_if_impl;
2005 template<template<class...> class L, class... T, template<class...> class P>
2006 struct mp_count_if_impl<L<T...>, P>
2008 using type = mp_plus<P<T>...>;
2011 template<class L, template<class...> class P>
2012 using mp_count_if = typename mp_count_if_impl<L, P>::type;</code></pre>
2015 <div class="paragraph">
2016 <p>at least if we require <code>P</code> to return <code>bool</code>. If not, we’ll have to coerce
2017 <code>P<T>::value</code> to 0 or 1, or the count will not be correct.</p>
2019 <div class="listingblock">
2020 <div class="content">
2021 <pre class="highlight"><code>template<bool v> using mp_bool = std::integral_constant<bool, v>;
2023 template<class L, template<class...> class P> struct mp_count_if_impl;
2025 template<template<class...> class L, class... T, template<class...> class P>
2026 struct mp_count_if_impl<L<T...>, P>
2028 using type = mp_plus<mp_bool<P<T>::value != 0>...>;
2031 template<class L, template<class...> class P>
2032 using mp_count_if = typename mp_count_if_impl<L, P>::type;</code></pre>
2035 <div class="paragraph">
2036 <p>The last primitive I’ll show is <code>mp_contains</code>. <code>mp_contains<L, V></code> returns
2037 whether the list <code>L</code> contains the type <code>V</code>:</p>
2039 <div class="listingblock">
2040 <div class="content">
2041 <pre class="highlight"><code>template<class L, class V> using mp_contains = mp_bool<mp_count<L, V>::value != 0>;</code></pre>
2044 <div class="paragraph">
2045 <p>At first sight, this implementation appears horribly naive and inefficient — why would we need to count all the occurrences just to throw that away if we’re
2046 only interested in a boolean result — but it’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>
2050 <div class="listingblock">
2051 <div class="content">
2052 <pre class="highlight"><code>template<class T1, class T2, class T3, class T4, class T5,
2053 class T6, class T7, class T8, class T9, class T10, class... T>
2054 struct mp_plus_impl<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>
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<T...>::value;
2060 using type = std::integral_constant<
2061 typename std::remove_const<decltype(_v)>::type, _v>;
2065 <div class="paragraph">
2066 <p>This cuts the number of template instantiations approximately tenfold.</p>
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++11 that</p>
2079 <p>takes advantage of variadic templates, parameter pack expansion, and template
2083 <p>operates on any variadic template <code>L<T...></code>, treating it as its
2084 fundamental data structure, without mandating a specific type list
2088 <p>uses template aliases as its metafunctions, with the expression <code>F<T...></code>
2089 serving as the equivalent of a function call;</p>
2092 <p>exploits the structural similarity between the data structure <code>L<T...></code>
2093 and the metafunction call <code>F<T...></code>;</p>
2096 <p>leverages parameter pack expansion as much as possible, instead of using the
2097 traditional recursive implementations;</p>
2100 <p>relies on inline definitions of template aliases for function composition,
2101 instead of providing library support for this task.</p>
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++11 implementation techniques in the process.</p>
2119 <div id="footer-text">
2120 Last updated 2019-12-10 00:19:27 UTC
2125 *:not(pre)>code { background: none; color: #600000; }
2126 /* table tr.even, table tr.alt, table tr:nth-of-type(even) { background: none; } */