simple_cxx11_metaprogramming.html 93 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130
  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. X&lt;add_pointer&gt;; // works!</code></pre>
  584. </div>
  585. </div>
  586. <div class="paragraph">
  587. <p>These language improvements allow for C&#43;&#43;11 metaprogramming that is
  588. substantially different than its idiomatic C&#43;&#43;03 equivalent. Boost.MPL is no
  589. longer good enough, and <em>something must be done</em>. But what?</p>
  590. </div>
  591. </div>
  592. </div>
  593. <div class="sect1">
  594. <h2 id="type_lists_and_mp_rename">Type lists and mp_rename</h2>
  595. <div class="sectionbody">
  596. <div class="paragraph">
  597. <p>Let&#8217;s start with the basics. Our basic data structure will be the type list:</p>
  598. </div>
  599. <div class="listingblock">
  600. <div class="content">
  601. <pre class="highlight"><code>template&lt;class... T&gt; struct mp_list {};</code></pre>
  602. </div>
  603. </div>
  604. <div class="paragraph">
  605. <p>Why the <code>mp_</code> prefix? mp obviously stands for metaprogramming, but could we not
  606. have used a namespace?</p>
  607. </div>
  608. <div class="paragraph">
  609. <p>Indeed we could have. Past experience with Boost.MPL however indicates that
  610. name conflicts between our metaprogramming primitives and standard identifiers
  611. (such as <code>list</code>) and keywords (such as <code>if</code>, <code>int</code> or <code>true</code>) will be common
  612. and will be a source of problems. With a prefix, we avoid all that trouble.</p>
  613. </div>
  614. <div class="paragraph">
  615. <p>So we have our type list and can put things into it:</p>
  616. </div>
  617. <div class="listingblock">
  618. <div class="content">
  619. <pre class="highlight"><code>using list = mp_list&lt;int, char, float, double, void&gt;;</code></pre>
  620. </div>
  621. </div>
  622. <div class="paragraph">
  623. <p>but can&#8217;t do anything else with it yet. We&#8217;ll need a library of primitives that
  624. operate on <code>mp_list</code>s. But before we get into that, let&#8217;s consider another
  625. interesting question first.</p>
  626. </div>
  627. <div class="paragraph">
  628. <p>Suppose we have our library of primitives that can do things with a <code>mp_list</code>,
  629. but some other code hands us a type list that is not an <code>mp_list</code>, such as for
  630. example an <code>std::tuple&lt;int, float, void*&gt;</code>, or
  631. <code><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4115.html">std::packer</a>&lt;int,
  632. float, void*&gt;</code>.</p>
  633. </div>
  634. <div class="paragraph">
  635. <p>Suppose we need to modify this external list of types in some manner (change
  636. the types into pointers, perhaps) and give back the transformed result in the
  637. form it was given to us, <code>std::tuple&lt;int*, float*, void**&gt;</code> in the first
  638. case and <code>std::packer&lt;int*, float*, void**&gt;</code> in the second.</p>
  639. </div>
  640. <div class="paragraph">
  641. <p>To do that, we need to first convert <code>std::tuple&lt;int, float, void*&gt;</code> to
  642. <code>mp_list&lt;int, float, void*&gt;</code>, apply <code>add_pointer</code> to each element obtaining
  643. <code>mp_list&lt;int*, float*, void**&gt;</code>, then convert that back to <code>std::tuple</code>.</p>
  644. </div>
  645. <div class="paragraph">
  646. <p>These conversion steps are a quite common occurrence, and we&#8217;ll write a
  647. primitive that helps us perform them, called <code>mp_rename</code>. We want</p>
  648. </div>
  649. <div class="listingblock">
  650. <div class="content">
  651. <pre class="highlight"><code>mp_rename&lt;std::tuple&lt;int, float, void*&gt;, mp_list&gt;</code></pre>
  652. </div>
  653. </div>
  654. <div class="paragraph">
  655. <p>to give us</p>
  656. </div>
  657. <div class="listingblock">
  658. <div class="content">
  659. <pre class="highlight"><code>mp_list&lt;int, float, void*&gt;</code></pre>
  660. </div>
  661. </div>
  662. <div class="paragraph">
  663. <p>and conversely,</p>
  664. </div>
  665. <div class="listingblock">
  666. <div class="content">
  667. <pre class="highlight"><code>mp_rename&lt;mp_list&lt;int, float, void*&gt;, std::tuple&gt;</code></pre>
  668. </div>
  669. </div>
  670. <div class="paragraph">
  671. <p>to give us</p>
  672. </div>
  673. <div class="listingblock">
  674. <div class="content">
  675. <pre class="highlight"><code>std::tuple&lt;int, float, void*&gt;</code></pre>
  676. </div>
  677. </div>
  678. <div class="paragraph">
  679. <p>Here is the implementation of <code>mp_rename</code>:</p>
  680. </div>
  681. <div class="listingblock">
  682. <div class="content">
  683. <pre class="highlight"><code>template&lt;class A, template&lt;class...&gt; class B&gt; struct mp_rename_impl;
  684. template&lt;template&lt;class...&gt; class A, class... T, template&lt;class...&gt; class B&gt;
  685. struct mp_rename_impl&lt;A&lt;T...&gt;, B&gt;
  686. {
  687. using type = B&lt;T...&gt;;
  688. };
  689. template&lt;class A, template&lt;class...&gt; class B&gt;
  690. using mp_rename = typename mp_rename_impl&lt;A, B&gt;::type;</code></pre>
  691. </div>
  692. </div>
  693. <div class="paragraph">
  694. <p>(This pattern of a template alias forwarding to a class template doing the
  695. actual work is common; class templates can be specialized, whereas template
  696. aliases cannot.)</p>
  697. </div>
  698. <div class="paragraph">
  699. <p>Note that <code>mp_rename</code> does not treat any list type as special, not even
  700. <code>mp_list</code>; it can rename any variadic class template into any other. You could
  701. use it to rename <code>std::packer</code> to <code>std::tuple</code> to <code>std::variant</code> (once there is
  702. such a thing) and it will happily oblige.</p>
  703. </div>
  704. <div class="paragraph">
  705. <p>In fact, it can even rename non-variadic class templates, as in the following
  706. examples:</p>
  707. </div>
  708. <div class="listingblock">
  709. <div class="content">
  710. <pre class="highlight"><code>mp_rename&lt;std::pair&lt;int, float&gt;, std::tuple&gt; // -&gt; std::tuple&lt;int, float&gt;
  711. mp_rename&lt;mp_list&lt;int, float&gt;, std::pair&gt; // -&gt; std::pair&lt;int, float&gt;
  712. mp_rename&lt;std::shared_ptr&lt;int&gt;, std::unique_ptr&gt; // -&gt; std::unique_ptr&lt;int&gt;</code></pre>
  713. </div>
  714. </div>
  715. <div class="paragraph">
  716. <p>There is a limit to the magic; <code>unique_ptr</code> can&#8217;t be renamed to <code>shared_ptr</code>:</p>
  717. </div>
  718. <div class="listingblock">
  719. <div class="content">
  720. <pre class="highlight"><code>mp_rename&lt;std::unique_ptr&lt;int&gt;, std::shared_ptr&gt; // error</code></pre>
  721. </div>
  722. </div>
  723. <div class="paragraph">
  724. <p>because <code>unique_ptr&lt;int&gt;</code> is actually <code>unique_ptr&lt;int,
  725. std::default_delete&lt;int&gt;&gt;</code> and <code>mp_rename</code> renames it to <code>shared_ptr&lt;int,
  726. std::default_delete&lt;int&gt;&gt;</code>, which doesn&#8217;t compile. But it still works in many
  727. more cases than one would naively expect at first.</p>
  728. </div>
  729. <div class="paragraph">
  730. <p>With conversions no longer a problem, let&#8217;s move on to primitives and define a
  731. simple one, <code>mp_size</code>, for practice. We want <code>mp_size&lt;mp_list&lt;T...&gt;&gt;</code> to
  732. give us the number of elements in the list, that is, the value of the
  733. expression <code>sizeof...(T)</code>.</p>
  734. </div>
  735. <div class="listingblock">
  736. <div class="content">
  737. <pre class="highlight"><code>template&lt;class L&gt; struct mp_size_impl;
  738. template&lt;class... T&gt; struct mp_size_impl&lt;mp_list&lt;T...&gt;&gt;
  739. {
  740. using type = std::integral_constant&lt;std::size_t, sizeof...(T)&gt;;
  741. };
  742. template&lt;class L&gt; using mp_size = typename mp_size_impl&lt;L&gt;::type;</code></pre>
  743. </div>
  744. </div>
  745. <div class="paragraph">
  746. <p>This is relatively straightforward, except for the <code>std::integral_constant</code>.
  747. What is it and why do we need it?</p>
  748. </div>
  749. <div class="paragraph">
  750. <p><code>std::integral_constant</code> is a standard C&#43;&#43;11 type that wraps an integral
  751. constant (that is, a compile-time constant integer value) into a type.</p>
  752. </div>
  753. <div class="paragraph">
  754. <p>Since metaprogramming operates on type lists, which can only hold types, it&#8217;s
  755. convenient to represent compile-time constants as types. This allows us to
  756. treat lists of types and lists of values in a uniform manner. It is therefore
  757. idiomatic in metaprogramming to take and return types instead of values, and
  758. this is what we have done. If at some later point we want the actual value, we
  759. can use the expression <code>mp_size&lt;L&gt;::value</code> to retrieve it.</p>
  760. </div>
  761. <div class="paragraph">
  762. <p>We now have our <code>mp_size</code>, but you may have noticed that there&#8217;s an interesting
  763. difference between <code>mp_size</code> and <code>mp_rename</code>. Whereas I made a point of
  764. <code>mp_rename</code> not treating <code>mp_list</code> as a special case, <code>mp_size</code> very much does:</p>
  765. </div>
  766. <div class="listingblock">
  767. <div class="content">
  768. <pre class="highlight"><code>template&lt;class... T&gt; struct mp_size_impl&lt;mp_list&lt;T...&gt;&gt;</code></pre>
  769. </div>
  770. </div>
  771. <div class="paragraph">
  772. <p>Is this really necessary? Can we not use the same technique in the
  773. implementation of <code>mp_size</code> as we did in <code>mp_rename</code>?</p>
  774. </div>
  775. <div class="listingblock">
  776. <div class="content">
  777. <pre class="highlight"><code>template&lt;class L&gt; struct mp_size_impl;
  778. template&lt;template&lt;class...&gt; class L, class... T&gt; struct mp_size_impl&lt;L&lt;T...&gt;&gt;
  779. {
  780. using type = std::integral_constant&lt;std::size_t, sizeof...(T)&gt;;
  781. };
  782. template&lt;class L&gt; using mp_size = typename mp_size_impl&lt;L&gt;::type;</code></pre>
  783. </div>
  784. </div>
  785. <div class="paragraph">
  786. <p>Yes, we very much can, and this improvement allows us to use <code>mp_size</code> on any
  787. other type lists, such as <code>std::tuple</code>. It turns <code>mp_size</code> into a truly generic
  788. primitive.</p>
  789. </div>
  790. <div class="paragraph">
  791. <p>This is nice. It is so nice that I&#8217;d argue that all our metaprogramming
  792. primitives ought to have this property. If someone hands us a type list in the
  793. form of an <code>std::tuple</code>, we should be able to operate on it directly, avoiding
  794. the conversions to and from <code>mp_list</code>.</p>
  795. </div>
  796. <div class="paragraph">
  797. <p>So do we no longer have any need for <code>mp_rename</code>? Not quite. Apart from the
  798. fact that sometimes we really do need to rename type lists, there is another
  799. surprising task for which <code>mp_rename</code> is useful.</p>
  800. </div>
  801. <div class="paragraph">
  802. <p>To illustrate it, let me introduce the primitive <code>mp_length</code>. It&#8217;s similar to
  803. <code>mp_size</code>, but while <code>mp_size</code> takes a type list as an argument, <code>mp_length</code>
  804. takes a variadic parameter pack and returns its length; or, stated differently,
  805. it returns its number of arguments:</p>
  806. </div>
  807. <div class="listingblock">
  808. <div class="content">
  809. <pre class="highlight"><code>template&lt;class... T&gt; using mp_length =
  810. std::integral_constant&lt;std::size_t, sizeof...(T)&gt;;</code></pre>
  811. </div>
  812. </div>
  813. <div class="paragraph">
  814. <p>How would we implement <code>mp_size</code> in terms of <code>mp_length</code>? One option is to just
  815. substitute the implementation of the latter into the former:</p>
  816. </div>
  817. <div class="listingblock">
  818. <div class="content">
  819. <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;
  820. {
  821. using type = mp_length&lt;T...&gt;;
  822. };</code></pre>
  823. </div>
  824. </div>
  825. <div class="paragraph">
  826. <p>but there is another way, much less mundane. Think about what <code>mp_size</code> does.
  827. It takes the argument</p>
  828. </div>
  829. <div class="listingblock">
  830. <div class="content">
  831. <pre class="highlight"><code><strong>mp_list</strong>&lt;int, void, float&gt;</code></pre>
  832. </div>
  833. </div>
  834. <div class="paragraph">
  835. <p>and returns</p>
  836. </div>
  837. <div class="listingblock">
  838. <div class="content">
  839. <pre class="highlight"><code><strong>mp_length</strong>&lt;int, void, float&gt;</code></pre>
  840. </div>
  841. </div>
  842. <div class="paragraph">
  843. <p>Do we already have a primitive that does a similar thing?</p>
  844. </div>
  845. <div class="paragraph">
  846. <p>(Not much of a choice, is there?)</p>
  847. </div>
  848. <div class="paragraph">
  849. <p>Indeed we have, and it&#8217;s called <code>mp_rename</code>.</p>
  850. </div>
  851. <div class="listingblock">
  852. <div class="content">
  853. <pre class="highlight"><code>template&lt;class L&gt; using mp_size = mp_rename&lt;L, mp_length&gt;;</code></pre>
  854. </div>
  855. </div>
  856. <div class="paragraph">
  857. <p>I don&#8217;t know about you, but I find this technique fascinating. It exploits the
  858. structural similarity between a list, <code>L&lt;T...&gt;</code>, and a metafunction "call",
  859. <code>F&lt;T...&gt;</code>, and the fact that the language sees the things the same way and
  860. allows us to pass the template alias <code>mp_length</code> to <code>mp_rename</code> as if it were
  861. an ordinary class template such as <code>mp_list</code>.</p>
  862. </div>
  863. <div class="paragraph">
  864. <p>(Other metaprogramming libraries provide a dedicated <code>apply</code> primitive for
  865. this job. <code>apply&lt;F, L&gt;</code> calls the metafunction <code>F</code> with the contents of the
  866. 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
  867. readability.)</p>
  868. </div>
  869. <div class="listingblock">
  870. <div class="content">
  871. <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>
  872. </div>
  873. </div>
  874. </div>
  875. </div>
  876. <div class="sect1">
  877. <h2 id="mp_transform">mp_transform</h2>
  878. <div class="sectionbody">
  879. <div class="paragraph">
  880. <p>Let&#8217;s revisit the example I gave earlier - someone hands us <code>std::tuple&lt;X, Y,
  881. Z&gt;</code> and we need to compute <code>std::tuple&lt;X*, Y*, Z*&gt;</code>. We already have
  882. <code>add_pointer</code>:</p>
  883. </div>
  884. <div class="listingblock">
  885. <div class="content">
  886. <pre class="highlight"><code>template&lt;class T&gt; using add_pointer = T*;</code></pre>
  887. </div>
  888. </div>
  889. <div class="paragraph">
  890. <p>so we just need to apply it to each element of the input tuple.</p>
  891. </div>
  892. <div class="paragraph">
  893. <p>The algorithm that takes a function and a list and applies the function to each
  894. element is called <code>transform</code> in Boost.MPL and the STL and <code>map</code> in functional
  895. languages. We&#8217;ll use <code>transform</code>, for consistency with the established C&#43;&#43;
  896. practice (<code>map</code> is a data structure in both the STL and Boost.MPL.)</p>
  897. </div>
  898. <div class="paragraph">
  899. <p>We&#8217;ll call our algorithm <code>mp_transform</code>, and <code>mp_transform&lt;F, L&gt;</code> will apply
  900. <code>F</code> to each element of <code>L</code> and return the result. Usually, the argument order
  901. is reversed and the function comes last. Our reasons to put it at the front
  902. will become evident later.</p>
  903. </div>
  904. <div class="paragraph">
  905. <p>There are many ways to implement <code>mp_transform</code>; the one we&#8217;ll pick will make
  906. use of another primitive, <code>mp_push_front</code>. <code>mp_push_front&lt;L, T&gt;</code>, as its name
  907. implies, adds <code>T</code> as a first element in <code>L</code>:</p>
  908. </div>
  909. <div class="listingblock">
  910. <div class="content">
  911. <pre class="highlight"><code>template&lt;class L, class T&gt; struct mp_push_front_impl;
  912. template&lt;template&lt;class...&gt; class L, class... U, class T&gt;
  913. struct mp_push_front_impl&lt;L&lt;U...&gt;, T&gt;
  914. {
  915. using type = L&lt;T, U...&gt;;
  916. };
  917. template&lt;class L, class T&gt;
  918. using mp_push_front = typename mp_push_front_impl&lt;L, T&gt;::type;</code></pre>
  919. </div>
  920. </div>
  921. <div class="paragraph">
  922. <p>There is no reason to constrain <code>mp_push_front</code> to a single element though. In
  923. C&#43;&#43;11, variadic templates should be our default choice, and the
  924. implementation of <code>mp_push_front</code> that can take an arbitrary number of elements
  925. is almost identical:</p>
  926. </div>
  927. <div class="listingblock">
  928. <div class="content">
  929. <pre class="highlight"><code>template&lt;class L, class... T&gt; struct mp_push_front_impl;
  930. template&lt;template&lt;class...&gt; class L, class... U, class... T&gt;
  931. struct mp_push_front_impl&lt;L&lt;U...&gt;, T...&gt;
  932. {
  933. using type = L&lt;T..., U...&gt;;
  934. };
  935. template&lt;class L, class... T&gt;
  936. using mp_push_front = typename mp_push_front_impl&lt;L, T...&gt;::type;</code></pre>
  937. </div>
  938. </div>
  939. <div class="paragraph">
  940. <p>On to <code>mp_transform</code>:</p>
  941. </div>
  942. <div class="listingblock">
  943. <div class="content">
  944. <pre class="highlight"><code>template&lt;template&lt;class...&gt; class F, class L&gt; struct mp_transform_impl;
  945. template&lt;template&lt;class...&gt; class F, class L&gt;
  946. using mp_transform = typename mp_transform_impl&lt;F, L&gt;::type;
  947. template&lt;template&lt;class...&gt; class F, template&lt;class...&gt; class L&gt;
  948. struct mp_transform_impl&lt;F, L&lt;&gt;&gt;
  949. {
  950. using type = L&lt;&gt;;
  951. };
  952. template&lt;template&lt;class...&gt; class F, template&lt;class...&gt; class L, class T1, class... T&gt;
  953. struct mp_transform_impl&lt;F, L&lt;T1, T...&gt;&gt;
  954. {
  955. using _first = F&lt;T1&gt;;
  956. using _rest = mp_transform&lt;F, L&lt;T...&gt;&gt;;
  957. using type = mp_push_front&lt;_rest, _first&gt;;
  958. };</code></pre>
  959. </div>
  960. </div>
  961. <div class="paragraph">
  962. <p>This is a straightforward recursive implementation that should be familiar to
  963. people with functional programming background.</p>
  964. </div>
  965. <div class="paragraph">
  966. <p>Can we do better? It turns out that in C&#43;&#43;11, we can.</p>
  967. </div>
  968. <div class="listingblock">
  969. <div class="content">
  970. <pre class="highlight"><code>template&lt;template&lt;class...&gt; class F, class L&gt; struct mp_transform_impl;
  971. template&lt;template&lt;class...&gt; class F, class L&gt;
  972. using mp_transform = typename mp_transform_impl&lt;F, L&gt;::type;
  973. template&lt;template&lt;class...&gt; class F, template&lt;class...&gt; class L, class... T&gt;
  974. struct mp_transform_impl&lt;F, L&lt;T...&gt;&gt;
  975. {
  976. using type = L&lt;F&lt;T&gt;...&gt;;
  977. };</code></pre>
  978. </div>
  979. </div>
  980. <div class="paragraph">
  981. <p>Here we take advantage of the fact that pack expansion is built into the
  982. language, so the <code>F&lt;T&gt;...</code> part does all the iteration work for us.</p>
  983. </div>
  984. <div class="paragraph">
  985. <p>We can now solve our original challenge: given an <code>std::tuple</code> of types, return
  986. an <code>std::tuple</code> of pointers to these types:</p>
  987. </div>
  988. <div class="listingblock">
  989. <div class="content">
  990. <pre class="highlight"><code>using input = std::tuple&lt;int, void, float&gt;;
  991. using expected = std::tuple&lt;int*, void*, float*&gt;;
  992. using result = mp_transform&lt;add_pointer, input&gt;;
  993. static_assert( std::is_same&lt;result, expected&gt;::value, "" );</code></pre>
  994. </div>
  995. </div>
  996. </div>
  997. </div>
  998. <div class="sect1">
  999. <h2 id="mp_transform_part_two">mp_transform, part two</h2>
  1000. <div class="sectionbody">
  1001. <div class="paragraph">
  1002. <p>What if we had a pair of tuples as input, and had to produce the corresponding
  1003. tuple of pairs? For example, given</p>
  1004. </div>
  1005. <div class="listingblock">
  1006. <div class="content">
  1007. <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>
  1008. </div>
  1009. </div>
  1010. <div class="paragraph">
  1011. <p>we had to produce</p>
  1012. </div>
  1013. <div class="listingblock">
  1014. <div class="content">
  1015. <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>
  1016. </div>
  1017. </div>
  1018. <div class="paragraph">
  1019. <p>We need to take the two lists, represented by tuples in the input, and combine
  1020. them pairwise by using <code>std::pair</code>. If we think of <code>std::pair</code> as a function
  1021. <code>F</code>, this task appears very similar to <code>mp_transform</code>, except we need to use a
  1022. binary function and two lists.</p>
  1023. </div>
  1024. <div class="paragraph">
  1025. <p>Changing our unary transform algorithm into a binary one isn&#8217;t hard:</p>
  1026. </div>
  1027. <div class="listingblock">
  1028. <div class="content">
  1029. <pre class="highlight"><code>template&lt;template&lt;class...&gt; class F, class L1, class L2&gt;
  1030. struct mp_transform2_impl;
  1031. template&lt;template&lt;class...&gt; class F, class L1, class L2&gt;
  1032. using mp_transform2 = typename mp_transform2_impl&lt;F, L1, L2&gt;::type;
  1033. template&lt;template&lt;class...&gt; class F,
  1034. template&lt;class...&gt; class L1, class... T1,
  1035. template&lt;class...&gt; class L2, class... T2&gt;
  1036. struct mp_transform2_impl&lt;F, L1&lt;T1...&gt;, L2&lt;T2...&gt;&gt;
  1037. {
  1038. static_assert( sizeof...(T1) == sizeof...(T2),
  1039. "The arguments of mp_transform2 should be of the same size" );
  1040. using type = L1&lt;F&lt;T1,T2&gt;...&gt;;
  1041. };</code></pre>
  1042. </div>
  1043. </div>
  1044. <div class="paragraph">
  1045. <p>and we can now do</p>
  1046. </div>
  1047. <div class="listingblock">
  1048. <div class="content">
  1049. <pre class="highlight"><code>using input = std::pair&lt;std::tuple&lt;X1, X2, X3&gt;, std::tuple&lt;Y1, Y2, Y3&gt;&gt;;
  1050. using expected = std::tuple&lt;std::pair&lt;X1, Y1&gt;, std::pair&lt;X2, Y2&gt;, std::pair&lt;X3, Y3&gt;&gt;;
  1051. using result = mp_transform2&lt;std::pair, input::first_type, input::second_type&gt;;
  1052. static_assert( std::is_same&lt;result, expected&gt;::value, "" );</code></pre>
  1053. </div>
  1054. </div>
  1055. <div class="paragraph">
  1056. <p>again exploiting the similarity between metafunctions and ordinary class
  1057. templates such as <code>std::pair</code>, this time in the other direction; we pass
  1058. <code>std::pair</code> where <code>mp_transform2</code> expects a metafunction.</p>
  1059. </div>
  1060. <div class="paragraph">
  1061. <p>Do we <em>have</em> to use separate transform algorithms for each arity though? If we
  1062. need a transform algorithm that takes a ternary function and three lists,
  1063. should we name it <code>mp_transform3</code>? No, this is exactly why we put the function
  1064. first. We just have to change <code>mp_transform</code> to be variadic:</p>
  1065. </div>
  1066. <div class="listingblock">
  1067. <div class="content">
  1068. <pre class="highlight"><code>template&lt;template&lt;class...&gt; class F, class... L&gt; struct mp_transform_impl;
  1069. template&lt;template&lt;class...&gt; class F, class... L&gt;
  1070. using mp_transform = typename mp_transform_impl&lt;F, L...&gt;::type;</code></pre>
  1071. </div>
  1072. </div>
  1073. <div class="paragraph">
  1074. <p>and then add the unary and binary specializations:</p>
  1075. </div>
  1076. <div class="listingblock">
  1077. <div class="content">
  1078. <pre class="highlight"><code>template&lt;template&lt;class...&gt; class F, template&lt;class...&gt; class L, class... T&gt;
  1079. struct mp_transform_impl&lt;F, L&lt;T...&gt;&gt;
  1080. {
  1081. using type = L&lt;F&lt;T&gt;...&gt;;
  1082. };
  1083. template&lt;template&lt;class...&gt; class F,
  1084. template&lt;class...&gt; class L1, class... T1,
  1085. template&lt;class...&gt; class L2, class... T2&gt;
  1086. struct mp_transform_impl&lt;F, L1&lt;T1...&gt;, L2&lt;T2...&gt;&gt;
  1087. {
  1088. static_assert( sizeof...(T1) == sizeof...(T2),
  1089. "The arguments of mp_transform should be of the same size" );
  1090. using type = L1&lt;F&lt;T1,T2&gt;...&gt;;
  1091. };</code></pre>
  1092. </div>
  1093. </div>
  1094. <div class="paragraph">
  1095. <p>We can also add ternary and further specializations.</p>
  1096. </div>
  1097. <div class="paragraph">
  1098. <p>Is it possible to implement the truly variadic <code>mp_transform</code>, one that works
  1099. with an arbitrary number of lists? It is in principle, and I&#8217;ll show one
  1100. possible abridged implementation here for completeness:</p>
  1101. </div>
  1102. <div class="listingblock">
  1103. <div class="content">
  1104. <pre class="highlight"><code>template&lt;template&lt;class...&gt; class F, class E, class... L&gt;
  1105. struct mp_transform_impl;
  1106. template&lt;template&lt;class...&gt; class F, class... L&gt;
  1107. using mp_transform = typename mp_transform_impl&lt;F, mp_empty&lt;L...&gt;, L...&gt;::type;
  1108. template&lt;template&lt;class...&gt; class F, class L1, class... L&gt;
  1109. struct mp_transform_impl&lt;F, mp_true, L1, L...&gt;
  1110. {
  1111. using type = mp_clear&lt;L1&gt;;
  1112. };
  1113. template&lt;template&lt;class...&gt; class F, class... L&gt;
  1114. struct mp_transform_impl&lt;F, mp_false, L...&gt;
  1115. {
  1116. using _first = F&lt; typename mp_front_impl&lt;L&gt;::type... &gt;;
  1117. using _rest = mp_transform&lt; F, typename mp_pop_front_impl&lt;L&gt;::type... &gt;;
  1118. using type = mp_push_front&lt;_rest, _first&gt;;
  1119. };</code></pre>
  1120. </div>
  1121. </div>
  1122. <div class="paragraph">
  1123. <p>but will omit the primitives that it uses. These are</p>
  1124. </div>
  1125. <div class="ulist">
  1126. <ul>
  1127. <li>
  1128. <p><code>mp_true</code>&#8201;&#8212;&#8201;an alias for <code>std::integral_constant&lt;bool, true&gt;</code>.</p>
  1129. </li>
  1130. <li>
  1131. <p><code>mp_false</code>&#8201;&#8212;&#8201;an alias for <code>std::integral_constant&lt;bool, false&gt;</code>.</p>
  1132. </li>
  1133. <li>
  1134. <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>
  1135. otherwise.</p>
  1136. </li>
  1137. <li>
  1138. <p><code>mp_clear&lt;L&gt;</code>&#8201;&#8212;&#8201;returns an empty list of the same type as <code>L</code>.</p>
  1139. </li>
  1140. <li>
  1141. <p><code>mp_front&lt;L&gt;</code>&#8201;&#8212;&#8201;returns the first element of <code>L</code>.</p>
  1142. </li>
  1143. <li>
  1144. <p><code>mp_pop_front&lt;L&gt;</code>&#8201;&#8212;&#8201;returns <code>L</code> without its first element.</p>
  1145. </li>
  1146. </ul>
  1147. </div>
  1148. <div class="paragraph">
  1149. <p>There is one interesting difference between the recursive <code>mp_transform</code>
  1150. implementation and the language-based one. <code>mp_transform&lt;add_pointer,
  1151. std::pair&lt;int, float&gt;&gt;</code> works with the <code>F&lt;T&gt;...</code> implementation and fails
  1152. with the recursive one, because <code>std::pair</code> is not a real type list and can
  1153. only hold exactly two types.</p>
  1154. </div>
  1155. </div>
  1156. </div>
  1157. <div class="sect1">
  1158. <h2 id="the_infamous_tuple_cat_challenge">The infamous tuple_cat challenge</h2>
  1159. <div class="sectionbody">
  1160. <div class="paragraph">
  1161. <p>Eric Niebler, in his
  1162. <a href="http://ericniebler.com/2014/11/13/tiny-metaprogramming-library/">Tiny
  1163. Metaprogramming Library</a> article, gives the function
  1164. <a href="http://en.cppreference.com/w/cpp/utility/tuple/tuple_cat"><code>std::tuple_cat</code></a> as a
  1165. kind of a metaprogramming challenge. <code>tuple_cat</code> is a variadic template
  1166. function that takes a number of tuples and concatenates them into another
  1167. <code>std::tuple</code>. This is Eric&#8217;s solution:</p>
  1168. </div>
  1169. <div class="listingblock">
  1170. <div class="content">
  1171. <pre class="highlight"><code>namespace detail
  1172. {
  1173. template&lt;typename Ret, typename...Is, typename ...Ks,
  1174. typename Tuples&gt;
  1175. Ret tuple_cat_(typelist&lt;Is...&gt;, typelist&lt;Ks...&gt;,
  1176. Tuples tpls)
  1177. {
  1178. return Ret{std::get&lt;Ks::value&gt;(
  1179. std::get&lt;Is::value&gt;(tpls))...};
  1180. }
  1181. }
  1182. template&lt;typename...Tuples,
  1183. typename Res =
  1184. typelist_apply_t&lt;
  1185. meta_quote&lt;std::tuple&gt;,
  1186. typelist_cat_t&lt;typelist&lt;as_typelist_t&lt;Tuples&gt;...&gt; &gt; &gt; &gt;
  1187. Res tuple_cat(Tuples &amp;&amp;... tpls)
  1188. {
  1189. static constexpr std::size_t N = sizeof...(Tuples);
  1190. // E.g. [0,0,0,2,2,2,3,3]
  1191. using inner =
  1192. typelist_cat_t&lt;
  1193. typelist_transform_t&lt;
  1194. typelist&lt;as_typelist_t&lt;Tuples&gt;...&gt;,
  1195. typelist_transform_t&lt;
  1196. as_typelist_t&lt;make_index_sequence&lt;N&gt; &gt;,
  1197. meta_quote&lt;meta_always&gt; &gt;,
  1198. meta_quote&lt;typelist_transform_t&gt; &gt; &gt;;
  1199. // E.g. [0,1,2,0,1,2,0,1]
  1200. using outer =
  1201. typelist_cat_t&lt;
  1202. typelist_transform_t&lt;
  1203. typelist&lt;as_typelist_t&lt;Tuples&gt;...&gt;,
  1204. meta_compose&lt;
  1205. meta_quote&lt;as_typelist_t&gt;,
  1206. meta_quote_i&lt;std::size_t, make_index_sequence&gt;,
  1207. meta_quote&lt;typelist_size_t&gt; &gt; &gt; &gt;;
  1208. return detail::tuple_cat_&lt;Res&gt;(
  1209. inner{},
  1210. outer{},
  1211. std::forward_as_tuple(std::forward&lt;Tuples&gt;(tpls)...));
  1212. }</code></pre>
  1213. </div>
  1214. </div>
  1215. <div class="paragraph">
  1216. <p>All right, challenge accepted. Let&#8217;s see what we can do.</p>
  1217. </div>
  1218. <div class="paragraph">
  1219. <p>As Eric explains, this implementation relies on the clever trick of packing the
  1220. input tuples into a tuple, creating two arrays of indices, <code>inner</code> and <code>outer</code>,
  1221. then indexing the outer tuple with the outer indices and the result, which is
  1222. one of our input tuples, with the inner indices.</p>
  1223. </div>
  1224. <div class="paragraph">
  1225. <p>So, for example, if tuple_cat is invoked as</p>
  1226. </div>
  1227. <div class="listingblock">
  1228. <div class="content">
  1229. <pre class="highlight"><code>std::tuple&lt;int, short, long&gt; t1;
  1230. std::tuple&lt;&gt; t2;
  1231. std::tuple&lt;float, double, long double&gt; t3;
  1232. std::tuple&lt;void*, char*&gt; t4;
  1233. auto res = tuple_cat(t1, t2, t3, t4);</code></pre>
  1234. </div>
  1235. </div>
  1236. <div class="paragraph">
  1237. <p>we&#8217;ll create the tuple</p>
  1238. </div>
  1239. <div class="listingblock">
  1240. <div class="content">
  1241. <pre class="highlight"><code>std::tuple&lt;std::tuple&lt;int, short, long&gt;, std::tuple&lt;&gt;,
  1242. std::tuple&lt;float, double, long double&gt;, std::tuple&lt;void*, char*&gt;&gt; t{t1, t2, t3, t4};</code></pre>
  1243. </div>
  1244. </div>
  1245. <div class="paragraph">
  1246. <p>and then extract the elements of t via</p>
  1247. </div>
  1248. <div class="listingblock">
  1249. <div class="content">
  1250. <pre class="highlight"><code>std::get&lt;0&gt;(std::get&lt;0&gt;(t)), // t1[0]
  1251. std::get&lt;1&gt;(std::get&lt;0&gt;(t)), // t1[1]
  1252. std::get&lt;2&gt;(std::get&lt;0&gt;(t)), // t1[2]
  1253. std::get&lt;0&gt;(std::get&lt;2&gt;(t)), // t3[0]
  1254. std::get&lt;1&gt;(std::get&lt;2&gt;(t)), // t3[1]
  1255. std::get&lt;2&gt;(std::get&lt;2&gt;(t)), // t3[2]
  1256. std::get&lt;0&gt;(std::get&lt;3&gt;(t)), // t4[0]
  1257. std::get&lt;1&gt;(std::get&lt;3&gt;(t)), // t4[1]</code></pre>
  1258. </div>
  1259. </div>
  1260. <div class="paragraph">
  1261. <p>(<code>t2</code> is empty, so we take nothing from it.)</p>
  1262. </div>
  1263. <div class="paragraph">
  1264. <p>The first column of integers is the <code>outer</code> array, the second one - the <code>inner</code>
  1265. array, and these are what we need to compute. But first, let&#8217;s deal with the
  1266. return type of <code>tuple_cat</code>.</p>
  1267. </div>
  1268. <div class="paragraph">
  1269. <p>The return type of <code>tuple_cat</code> is just the concatenation of the arguments,
  1270. viewed as type lists. The metaprogramming algorithm that concatenates lists is
  1271. called
  1272. <a href="https://ericniebler.github.io/meta/group__transformation.html"><code>meta::concat</code></a>
  1273. in Eric Niebler&#8217;s <a href="https://github.com/ericniebler/meta">Meta</a> library, but I&#8217;ll
  1274. call it <code>mp_append</code>, after its classic Lisp name.</p>
  1275. </div>
  1276. <div class="paragraph">
  1277. <p>(Lisp is today&#8217;s equivalent of Latin. Educated people are supposed to have
  1278. studied and forgotten it.)</p>
  1279. </div>
  1280. <div class="listingblock">
  1281. <div class="content">
  1282. <pre class="highlight"><code>template&lt;class... L&gt; struct mp_append_impl;
  1283. template&lt;class... L&gt; using mp_append = typename mp_append_impl&lt;L...&gt;::type;
  1284. template&lt;&gt; struct mp_append_impl&lt;&gt;
  1285. {
  1286. using type = mp_list&lt;&gt;;
  1287. };
  1288. template&lt;template&lt;class...&gt; class L, class... T&gt; struct mp_append_impl&lt;L&lt;T...&gt;&gt;
  1289. {
  1290. using type = L&lt;T...&gt;;
  1291. };
  1292. template&lt;template&lt;class...&gt; class L1, class... T1,
  1293. template&lt;class...&gt; class L2, class... T2, class... Lr&gt;
  1294. struct mp_append_impl&lt;L1&lt;T1...&gt;, L2&lt;T2...&gt;, Lr...&gt;
  1295. {
  1296. using type = mp_append&lt;L1&lt;T1..., T2...&gt;, Lr...&gt;;
  1297. };</code></pre>
  1298. </div>
  1299. </div>
  1300. <div class="paragraph">
  1301. <p>That was fairly easy. There are other ways to implement <code>mp_append</code>, but this
  1302. one demonstrates how the language does most of the work for us via pack
  1303. expansion. This is a common theme in C&#43;&#43;11.</p>
  1304. </div>
  1305. <div class="paragraph">
  1306. <p>Note how <code>mp_append</code> returns the same list type as its first argument. Of
  1307. course, in the case in which no arguments are given, there is no first argument
  1308. from which to take the type, so I&#8217;ve arbitrarily chosen to return an empty
  1309. <code>mp_list</code>.</p>
  1310. </div>
  1311. <div class="paragraph">
  1312. <p>We&#8217;re now ready with the declaration of <code>tuple_cat</code>:</p>
  1313. </div>
  1314. <div class="listingblock">
  1315. <div class="content">
  1316. <pre class="highlight"><code>template&lt;class... Tp,
  1317. class R = mp_append&lt;typename std::remove_reference&lt;Tp&gt;::type...&gt;&gt;
  1318. R tuple_cat( Tp &amp;&amp;... tp );</code></pre>
  1319. </div>
  1320. </div>
  1321. <div class="paragraph">
  1322. <p>The reason we need <code>remove_reference</code> is because of the rvalue reference
  1323. parameters, used to implement perfect forwarding. If the argument is an lvalue,
  1324. such as for example <code>t1</code> above, its corresponding type will be a reference to a
  1325. tuple&#8201;&#8212;&#8201;<code>std::tuple&lt;int, short, long&gt;&amp;</code> in <code>t1</code>'s case. Our primitives do
  1326. not recognize references to tuples as type lists, so we need to strip them off.</p>
  1327. </div>
  1328. <div class="paragraph">
  1329. <p>There are two problems with our return type computation though. One, what if
  1330. <code>tuple_cat</code> is called without any arguments? We return <code>mp_list&lt;&gt;</code> in that
  1331. case, but the correct result is <code>std::tuple&lt;&gt;</code>.</p>
  1332. </div>
  1333. <div class="paragraph">
  1334. <p>Two, what if we call <code>tuple_cat</code> with a first argument that is a <code>std::pair</code>?
  1335. We&#8217;ll try to append more elements to <code>std::pair</code>, and it will fail.</p>
  1336. </div>
  1337. <div class="paragraph">
  1338. <p>We can solve both our problems by using an empty tuple as the first argument to
  1339. <code>mp_append</code>:</p>
  1340. </div>
  1341. <div class="listingblock">
  1342. <div class="content">
  1343. <pre class="highlight"><code>template&lt;class... Tp,
  1344. class R = mp_append&lt;std::tuple&lt;&gt;, typename std::remove_reference&lt;Tp&gt;::type...&gt;&gt;
  1345. R tuple_cat( Tp &amp;&amp;... tp );</code></pre>
  1346. </div>
  1347. </div>
  1348. <div class="paragraph">
  1349. <p>With the return type taken care of, let&#8217;s now move on to computing inner. We
  1350. have</p>
  1351. </div>
  1352. <div class="listingblock">
  1353. <div class="content">
  1354. <pre class="highlight"><code>[x1, x2, x3], [], [y1, y2, y3], [z1, z2]</code></pre>
  1355. </div>
  1356. </div>
  1357. <div class="paragraph">
  1358. <p>as input and we need to output</p>
  1359. </div>
  1360. <div class="listingblock">
  1361. <div class="content">
  1362. <pre class="highlight"><code>[0, 0, 0, 2, 2, 2, 3, 3]</code></pre>
  1363. </div>
  1364. </div>
  1365. <div class="paragraph">
  1366. <p>which is the concatenation of</p>
  1367. </div>
  1368. <div class="listingblock">
  1369. <div class="content">
  1370. <pre class="highlight"><code>[0, 0, 0], [], [2, 2, 2], [3, 3]</code></pre>
  1371. </div>
  1372. </div>
  1373. <div class="paragraph">
  1374. <p>Here each tuple is the same size as the input, but is filled with a constant
  1375. that represents its index in the argument list. The first tuple is filled with
  1376. 0, the second with 1, the third with 2, and so on.</p>
  1377. </div>
  1378. <div class="paragraph">
  1379. <p>We can achieve this result if we first compute a list of indices, in our case
  1380. <code>[0, 1, 2, 3]</code>, then use binary <code>mp_transform</code> on the two lists</p>
  1381. </div>
  1382. <div class="listingblock">
  1383. <div class="content">
  1384. <pre class="highlight"><code>[[x1, x2, x3], [], [y1, y2, y3], [z1, z2]]
  1385. [0, 1, 2, 3]</code></pre>
  1386. </div>
  1387. </div>
  1388. <div class="paragraph">
  1389. <p>and a function which takes a list and an integer (in the form of an
  1390. <code>std::integral_constant</code>) and returns a list that is the same size as the
  1391. original, but filled with the second argument.</p>
  1392. </div>
  1393. <div class="paragraph">
  1394. <p>We&#8217;ll call this function <code>mp_fill</code>, after <code>std::fill</code>.</p>
  1395. </div>
  1396. <div class="paragraph">
  1397. <p>Functional programmers will immediately realize that <code>mp_fill</code> is
  1398. <code>mp_transform</code> with a function that returns a constant, and here&#8217;s an
  1399. implementation along these lines:</p>
  1400. </div>
  1401. <div class="listingblock">
  1402. <div class="content">
  1403. <pre class="highlight"><code>template&lt;class V&gt; struct mp_constant
  1404. {
  1405. template&lt;class...&gt; using apply = V;
  1406. };
  1407. template&lt;class L, class V&gt;
  1408. using mp_fill = mp_transform&lt;mp_constant&lt;V&gt;::template apply, L&gt;;</code></pre>
  1409. </div>
  1410. </div>
  1411. <div class="paragraph">
  1412. <p>Here&#8217;s an alternate implementation:</p>
  1413. </div>
  1414. <div class="listingblock">
  1415. <div class="content">
  1416. <pre class="highlight"><code>template&lt;class L, class V&gt; struct mp_fill_impl;
  1417. template&lt;template&lt;class...&gt; class L, class... T, class V&gt;
  1418. struct mp_fill_impl&lt;L&lt;T...&gt;, V&gt;
  1419. {
  1420. template&lt;class...&gt; using _fv = V;
  1421. using type = L&lt;_fv&lt;T&gt;...&gt;;
  1422. };
  1423. template&lt;class L, class V&gt; using mp_fill = typename mp_fill_impl&lt;L, V&gt;::type;</code></pre>
  1424. </div>
  1425. </div>
  1426. <div class="paragraph">
  1427. <p>These demonstrate different styles and choosing one over the other is largely a
  1428. matter of taste here. In the first case, we combine existing primitives; in the
  1429. second case, we "inline" <code>mp_const</code> and even <code>mp_transform</code> in the body of
  1430. <code>mp_fill_impl</code>.</p>
  1431. </div>
  1432. <div class="paragraph">
  1433. <p>Most C&#43;&#43;11 programmers will probably find the second implementation easier to
  1434. read.</p>
  1435. </div>
  1436. <div class="paragraph">
  1437. <p>We can now <code>mp_fill</code>, but we still need the <code>[0, 1, 2, 3]</code> index sequence. We
  1438. could write an algorithm <code>mp_iota</code> for that (named after
  1439. <a href="http://en.cppreference.com/w/cpp/algorithm/iota"><code>std::iota</code></a>), but it so
  1440. happens that C&#43;&#43;14 already has a standard way of generating an index
  1441. sequence, called
  1442. <a href="http://en.cppreference.com/w/cpp/utility/integer_sequence"><code>std::make_index_sequence</code></a>.
  1443. Since Eric&#8217;s original solution makes use of <code>make_index_sequence</code>, let&#8217;s follow
  1444. his lead.</p>
  1445. </div>
  1446. <div class="paragraph">
  1447. <p>Technically, this takes us outside of C&#43;&#43;11, but <code>make_index_sequence</code> is not
  1448. hard to implement (if efficiency is not a concern):</p>
  1449. </div>
  1450. <div class="listingblock">
  1451. <div class="content">
  1452. <pre class="highlight"><code>template&lt;class T, T... Ints&gt; struct integer_sequence
  1453. {
  1454. };
  1455. template&lt;class S&gt; struct next_integer_sequence;
  1456. template&lt;class T, T... Ints&gt; struct next_integer_sequence&lt;integer_sequence&lt;T, Ints...&gt;&gt;
  1457. {
  1458. using type = integer_sequence&lt;T, Ints..., sizeof...(Ints)&gt;;
  1459. };
  1460. template&lt;class T, T I, T N&gt; struct make_int_seq_impl;
  1461. template&lt;class T, T N&gt;
  1462. using make_integer_sequence = typename make_int_seq_impl&lt;T, 0, N&gt;::type;
  1463. template&lt;class T, T I, T N&gt; struct make_int_seq_impl
  1464. {
  1465. using type = typename next_integer_sequence&lt;
  1466. typename make_int_seq_impl&lt;T, I+1, N&gt;::type&gt;::type;
  1467. };
  1468. template&lt;class T, T N&gt; struct make_int_seq_impl&lt;T, N, N&gt;
  1469. {
  1470. using type = integer_sequence&lt;T&gt;;
  1471. };
  1472. template&lt;std::size_t... Ints&gt;
  1473. using index_sequence = integer_sequence&lt;std::size_t, Ints...&gt;;
  1474. template&lt;std::size_t N&gt;
  1475. using make_index_sequence = make_integer_sequence&lt;std::size_t, N&gt;;</code></pre>
  1476. </div>
  1477. </div>
  1478. <div class="paragraph">
  1479. <p>We can now obtain an <code>index_sequence&lt;0, 1, 2, 3&gt;</code>:</p>
  1480. </div>
  1481. <div class="listingblock">
  1482. <div class="content">
  1483. <pre class="highlight"><code>template&lt;class... Tp,
  1484. class R = mp_append&lt;std::tuple&lt;&gt;, typename std::remove_reference&lt;Tp&gt;::type...&gt;&gt;
  1485. R tuple_cat( Tp &amp;&amp;... tp )
  1486. {
  1487. std::size_t const N = sizeof...(Tp);
  1488. // inner
  1489. using seq = make_index_sequence&lt;N&gt;;
  1490. }</code></pre>
  1491. </div>
  1492. </div>
  1493. <div class="paragraph">
  1494. <p>but <code>make_index_sequence&lt;4&gt;</code> returns <code>integer_sequence&lt;std::size_t, 0, 1, 2,
  1495. 3&gt;</code>, which is not a type list. In order to work with it, we need to convert it
  1496. to a type list, so we&#8217;ll introduce a function <code>mp_from_sequence</code> that does
  1497. that.</p>
  1498. </div>
  1499. <div class="listingblock">
  1500. <div class="content">
  1501. <pre class="highlight"><code>template&lt;class S&gt; struct mp_from_sequence_impl;
  1502. template&lt;template&lt;class T, T... I&gt; class S, class U, U... J&gt;
  1503. struct mp_from_sequence_impl&lt;S&lt;U, J...&gt;&gt;
  1504. {
  1505. using type = mp_list&lt;std::integral_constant&lt;U, J&gt;...&gt;;
  1506. };
  1507. template&lt;class S&gt; using mp_from_sequence = typename mp_from_sequence_impl&lt;S&gt;::type;</code></pre>
  1508. </div>
  1509. </div>
  1510. <div class="paragraph">
  1511. <p>We can now compute the two lists that we wanted to transform with <code>mp_fill</code>:</p>
  1512. </div>
  1513. <div class="listingblock">
  1514. <div class="content">
  1515. <pre class="highlight"><code>template&lt;class... Tp,
  1516. class R = mp_append&lt;std::tuple&lt;&gt;, typename std::remove_reference&lt;Tp&gt;::type...&gt;&gt;
  1517. R tuple_cat( Tp &amp;&amp;... tp )
  1518. {
  1519. std::size_t const N = sizeof...(Tp);
  1520. // inner
  1521. using list1 = mp_list&lt;typename std::remove_reference&lt;Tp&gt;::type...&gt;;
  1522. using list2 = mp_from_sequence&lt;make_index_sequence&lt;N&gt;&gt;;
  1523. // list1: [[x1, x2, x3], [], [y1, y2, y3], [z1, z2]]
  1524. // list2: [0, 1, 2, 3]
  1525. return R{};
  1526. }</code></pre>
  1527. </div>
  1528. </div>
  1529. <div class="paragraph">
  1530. <p>and finish the job of computing <code>inner</code>:</p>
  1531. </div>
  1532. <div class="listingblock">
  1533. <div class="content">
  1534. <pre class="highlight"><code>template&lt;class... Tp,
  1535. class R = mp_append&lt;std::tuple&lt;&gt;, typename std::remove_reference&lt;Tp&gt;::type...&gt;&gt;
  1536. R tuple_cat( Tp &amp;&amp;... tp )
  1537. {
  1538. std::size_t const N = sizeof...(Tp);
  1539. // inner
  1540. using list1 = mp_list&lt;typename std::remove_reference&lt;Tp&gt;::type...&gt;;
  1541. using list2 = mp_from_sequence&lt;make_index_sequence&lt;N&gt;&gt;;
  1542. // list1: [[x1, x2, x3], [], [y1, y2, y3], [z1, z2]]
  1543. // list2: [0, 1, 2, 3]
  1544. using list3 = mp_transform&lt;mp_fill, list1, list2&gt;;
  1545. // list3: [[0, 0, 0], [], [2, 2, 2], [3, 3]]
  1546. using inner = mp_rename&lt;list3, mp_append&gt;; // or mp_apply&lt;mp_append, list3&gt;
  1547. // inner: [0, 0, 0, 2, 2, 2, 3, 3]
  1548. return R{};
  1549. }</code></pre>
  1550. </div>
  1551. </div>
  1552. <div class="paragraph">
  1553. <p>For <code>outer</code>, we again have</p>
  1554. </div>
  1555. <div class="listingblock">
  1556. <div class="content">
  1557. <pre class="highlight"><code>[x1, x2, x3], [], [y1, y2, y3], [z1, z2]</code></pre>
  1558. </div>
  1559. </div>
  1560. <div class="paragraph">
  1561. <p>as input and we need to output</p>
  1562. </div>
  1563. <div class="listingblock">
  1564. <div class="content">
  1565. <pre class="highlight"><code>[0, 1, 2, 0, 1, 2, 0, 1]</code></pre>
  1566. </div>
  1567. </div>
  1568. <div class="paragraph">
  1569. <p>which is the concatenation of</p>
  1570. </div>
  1571. <div class="listingblock">
  1572. <div class="content">
  1573. <pre class="highlight"><code>[0, 1, 2], [], [0, 1, 2], [0, 1]</code></pre>
  1574. </div>
  1575. </div>
  1576. <div class="paragraph">
  1577. <p>The difference here is that instead of filling the tuple with a constant value,
  1578. we need to fill it with increasing values, starting from 0, that is, with the
  1579. result of <code>make_index_sequence&lt;N&gt;</code>, where <code>N</code> is the number of elements.</p>
  1580. </div>
  1581. <div class="paragraph">
  1582. <p>The straightforward way to do that is to just define a metafunction <code>F</code> that
  1583. does what we want, then use <code>mp_transform</code> to apply it to the input:</p>
  1584. </div>
  1585. <div class="listingblock">
  1586. <div class="content">
  1587. <pre class="highlight"><code>template&lt;class N&gt; using mp_iota = mp_from_sequence&lt;make_index_sequence&lt;N::value&gt;&gt;;
  1588. template&lt;class L&gt; using F = mp_iota&lt;mp_size&lt;L&gt;&gt;;
  1589. template&lt;class... Tp,
  1590. class R = mp_append&lt;std::tuple&lt;&gt;, typename std::remove_reference&lt;Tp&gt;::type...&gt;&gt;
  1591. R tuple_cat( Tp &amp;&amp;... tp )
  1592. {
  1593. std::size_t const N = sizeof...(Tp);
  1594. // outer
  1595. using list1 = mp_list&lt;typename std::remove_reference&lt;Tp&gt;::type...&gt;;
  1596. using list2 = mp_transform&lt;F, list1&gt;;
  1597. // list2: [[0, 1, 2], [], [0, 1, 2], [0, 1]]
  1598. using outer = mp_rename&lt;list2, mp_append&gt;;
  1599. // outer: [0, 1, 2, 0, 1, 2, 0, 1]
  1600. return R{};
  1601. }</code></pre>
  1602. </div>
  1603. </div>
  1604. <div class="paragraph">
  1605. <p>Well that was easy. Surprisingly easy. The one small annoyance is that we can&#8217;t
  1606. define <code>F</code> inside <code>tuple_cat</code> - templates can&#8217;t be defined in functions.</p>
  1607. </div>
  1608. <div class="paragraph">
  1609. <p>Let&#8217;s put everything together.</p>
  1610. </div>
  1611. <div class="listingblock">
  1612. <div class="content">
  1613. <pre class="highlight"><code>template&lt;class N&gt; using mp_iota = mp_from_sequence&lt;make_index_sequence&lt;N::value&gt;&gt;;
  1614. template&lt;class L&gt; using F = mp_iota&lt;mp_size&lt;L&gt;&gt;;
  1615. template&lt;class R, class...Is, class... Ks, class Tp&gt;
  1616. R tuple_cat_( mp_list&lt;Is...&gt;, mp_list&lt;Ks...&gt;, Tp tp )
  1617. {
  1618. return R{ std::get&lt;Ks::value&gt;(std::get&lt;Is::value&gt;(tp))... };
  1619. }
  1620. template&lt;class... Tp,
  1621. class R = mp_append&lt;std::tuple&lt;&gt;, typename std::remove_reference&lt;Tp&gt;::type...&gt;&gt;
  1622. R tuple_cat( Tp &amp;&amp;... tp )
  1623. {
  1624. std::size_t const N = sizeof...(Tp);
  1625. // inner
  1626. using list1 = mp_list&lt;typename std::remove_reference&lt;Tp&gt;::type...&gt;;
  1627. using list2 = mp_from_sequence&lt;make_index_sequence&lt;N&gt;&gt;;
  1628. // list1: [[x1, x2, x3], [], [y1, y2, y3], [z1, z2]]
  1629. // list2: [0, 1, 2, 3]
  1630. using list3 = mp_transform&lt;mp_fill, list1, list2&gt;;
  1631. // list3: [[0, 0, 0], [], [2, 2, 2], [3, 3]]
  1632. using inner = mp_rename&lt;list3, mp_append&gt;; // or mp_apply&lt;mp_append, list3&gt;
  1633. // inner: [0, 0, 0, 2, 2, 2, 3, 3]
  1634. // outer
  1635. using list4 = mp_transform&lt;F, list1&gt;;
  1636. // list4: [[0, 1, 2], [], [0, 1, 2], [0, 1]]
  1637. using outer = mp_rename&lt;list4, mp_append&gt;;
  1638. // outer: [0, 1, 2, 0, 1, 2, 0, 1]
  1639. return tuple_cat_&lt;R&gt;( inner(), outer(),
  1640. std::forward_as_tuple( std::forward&lt;Tp&gt;(tp)... ) );
  1641. }</code></pre>
  1642. </div>
  1643. </div>
  1644. <div class="paragraph">
  1645. <p>This almost compiles, except that our <code>inner</code> happens to be a <code>std::tuple</code>, but
  1646. our helper function expects an <code>mp_list</code>. (<code>outer</code> is already an <code>mp_list</code>, by
  1647. sheer luck.) We can fix that easily enough.</p>
  1648. </div>
  1649. <div class="listingblock">
  1650. <div class="content">
  1651. <pre class="highlight"><code>return tuple_cat_&lt;R&gt;( mp_rename&lt;inner, mp_list&gt;(), outer(),
  1652. std::forward_as_tuple( std::forward&lt;Tp&gt;(tp)... ) );</code></pre>
  1653. </div>
  1654. </div>
  1655. <div class="paragraph">
  1656. <p>Let&#8217;s define a <code>print_tuple</code> function and see if everything checks out.</p>
  1657. </div>
  1658. <div class="listingblock">
  1659. <div class="content">
  1660. <pre class="highlight"><code>template&lt;int I, int N, class... T&gt; struct print_tuple_
  1661. {
  1662. void operator()( std::tuple&lt;T...&gt; const &amp; tp ) const
  1663. {
  1664. using Tp = typename std::tuple_element&lt;I, std::tuple&lt;T...&gt;&gt;::type;
  1665. print_type&lt;Tp&gt;( " ", ": " );
  1666. std::cout &lt;&lt; std::get&lt;I&gt;( tp ) &lt;&lt; ";";
  1667. print_tuple_&lt; I+1, N, T... &gt;()( tp );
  1668. }
  1669. };
  1670. template&lt;int N, class... T&gt; struct print_tuple_&lt;N, N, T...&gt;
  1671. {
  1672. void operator()( std::tuple&lt;T...&gt; const &amp; ) const
  1673. {
  1674. }
  1675. };
  1676. template&lt;class... T&gt; void print_tuple( std::tuple&lt;T...&gt; const &amp; tp )
  1677. {
  1678. std::cout &lt;&lt; "{";
  1679. print_tuple_&lt;0, sizeof...(T), T...&gt;()( tp );
  1680. std::cout &lt;&lt; " }\n";
  1681. }
  1682. int main()
  1683. {
  1684. std::tuple&lt;int, long&gt; t1{ 1, 2 };
  1685. std::tuple&lt;&gt; t2;
  1686. std::tuple&lt;float, double, long double&gt; t3{ 3, 4, 5 };
  1687. std::pair&lt;void const*, char const*&gt; t4{ "pv", "test" };
  1688. using expected = std::tuple&lt;int, long, float, double, long double,
  1689. void const*, char const*&gt;;
  1690. auto result = ::tuple_cat( t1, t2, t3, t4 );
  1691. static_assert( std::is_same&lt;decltype(result), expected&gt;::value, "" );
  1692. print_tuple( result );
  1693. }</code></pre>
  1694. </div>
  1695. </div>
  1696. <div class="paragraph">
  1697. <p>Output:</p>
  1698. </div>
  1699. <div class="listingblock">
  1700. <div class="content">
  1701. <pre class="highlight"><code>{ int: 1; long: 2; float: 3; double: 4; long double: 5; void const*: 0x407086;
  1702. char const*: test; }</code></pre>
  1703. </div>
  1704. </div>
  1705. <div class="paragraph">
  1706. <p>Seems to work. But there&#8217;s at least one error left. To see why, replace the
  1707. first tuple</p>
  1708. </div>
  1709. <div class="listingblock">
  1710. <div class="content">
  1711. <pre class="highlight"><code>std::tuple&lt;int, long&gt; t1{ 1, 2 };</code></pre>
  1712. </div>
  1713. </div>
  1714. <div class="paragraph">
  1715. <p>with a pair:</p>
  1716. </div>
  1717. <div class="listingblock">
  1718. <div class="content">
  1719. <pre class="highlight"><code>std::pair&lt;int, long&gt; t1{ 1, 2 };</code></pre>
  1720. </div>
  1721. </div>
  1722. <div class="paragraph">
  1723. <p>We now get an error at</p>
  1724. </div>
  1725. <div class="listingblock">
  1726. <div class="content">
  1727. <pre class="highlight"><code>using inner = mp_rename&lt;list3, mp_append&gt;;</code></pre>
  1728. </div>
  1729. </div>
  1730. <div class="paragraph">
  1731. <p>because the first element of <code>list3</code> is an <code>std::pair</code>, which <code>mp_append</code> tries
  1732. and fails to use as its return type.</p>
  1733. </div>
  1734. <div class="paragraph">
  1735. <p>There are two ways to fix that. The first one is to apply the same trick we
  1736. used for the return type, and insert an empty <code>mp_list</code> at the front of
  1737. <code>list3</code>, which <code>mp_append</code> will use as a return type:</p>
  1738. </div>
  1739. <div class="listingblock">
  1740. <div class="content">
  1741. <pre class="highlight"><code>using inner = mp_rename&lt;mp_push_front&lt;list3, mp_list&lt;&gt;&gt;, mp_append&gt;;</code></pre>
  1742. </div>
  1743. </div>
  1744. <div class="paragraph">
  1745. <p>The second way is to just convert all inputs to mp_list:</p>
  1746. </div>
  1747. <div class="listingblock">
  1748. <div class="content">
  1749. <pre class="highlight"><code>using list1 = mp_list&lt;
  1750. mp_rename&lt;typename std::remove_reference&lt;Tp&gt;::type, mp_list&gt;...&gt;;</code></pre>
  1751. </div>
  1752. </div>
  1753. <div class="paragraph">
  1754. <p>In both cases, inner will now be an <code>mp_list</code>, so we can omit the <code>mp_rename</code>
  1755. in the call to <code>tuple_cat_</code>.</p>
  1756. </div>
  1757. <div class="paragraph">
  1758. <p>We&#8217;re done. The results hopefully speak for themselves.</p>
  1759. </div>
  1760. </div>
  1761. </div>
  1762. <div class="sect1">
  1763. <h2 id="higher_order_metaprogramming_or_lack_thereof">Higher order metaprogramming, or lack thereof</h2>
  1764. <div class="sectionbody">
  1765. <div class="paragraph">
  1766. <p>Perhaps by now you&#8217;re wondering why this article is called "Simple C&#43;&#43;11
  1767. metaprogramming", since what we covered so far wasn&#8217;t particularly simple.</p>
  1768. </div>
  1769. <div class="paragraph">
  1770. <p>The <em>relative</em> simplicity of our approach stems from the fact that we&#8217;ve not
  1771. been doing any higher order metaprogramming, that is, we haven&#8217;t introduced any
  1772. primitives that return metafunctions, such as <code>compose</code>, <code>bind</code>, or a lambda
  1773. library.</p>
  1774. </div>
  1775. <div class="paragraph">
  1776. <p>I posit that such higher order metaprogramming is, in the majority of cases,
  1777. not necessary in C&#43;&#43;11. Consider, for example, Eric Niebler&#8217;s solution given
  1778. above:</p>
  1779. </div>
  1780. <div class="listingblock">
  1781. <div class="content">
  1782. <pre class="highlight"><code>using outer =
  1783. typelist_cat_t&lt;
  1784. typelist_transform_t&lt;
  1785. typelist&lt;as_typelist_t&lt;Tuples&gt;...&gt;,
  1786. meta_compose&lt;
  1787. meta_quote&lt;as_typelist_t&gt;,
  1788. meta_quote_i&lt;std::size_t, make_index_sequence&gt;,
  1789. meta_quote&lt;typelist_size_t&gt; &gt; &gt; &gt;;</code></pre>
  1790. </div>
  1791. </div>
  1792. <div class="paragraph">
  1793. <p>The <code>meta_compose</code> expression takes three other ("quoted") metafunctions and
  1794. creates a new metafunction that applies them in order. Eric uses this example
  1795. as motivation to introduce the concept of a "metafunction class" and then to
  1796. supply various primitives that operate on metafunction classes.</p>
  1797. </div>
  1798. <div class="paragraph">
  1799. <p>But when we have metafunctions <code>F</code>, <code>G</code> and <code>H</code>, instead of using
  1800. <code>meta_compose</code>, in C&#43;&#43;11 we can just do</p>
  1801. </div>
  1802. <div class="listingblock">
  1803. <div class="content">
  1804. <pre class="highlight"><code>template&lt;class... T&gt; using Fgh = F&lt;G&lt;H&lt;T...&gt;&gt;&gt;;</code></pre>
  1805. </div>
  1806. </div>
  1807. <div class="paragraph">
  1808. <p>and that&#8217;s it. The language makes defining composite functions easy, and there
  1809. is no need for library support. If the functions to be composed are
  1810. <code>as_typelist_t</code>, <code>std::make_index_sequence</code> and <code>typelist_size_t</code>, we just
  1811. define</p>
  1812. </div>
  1813. <div class="listingblock">
  1814. <div class="content">
  1815. <pre class="highlight"><code>template&lt;class... T&gt;
  1816. using F = as_typelist_t&lt;std::make_index_sequence&lt;typelist_size_t&lt;T...&gt;::value&gt;&gt;;</code></pre>
  1817. </div>
  1818. </div>
  1819. <div class="paragraph">
  1820. <p>Similarly, if we need a metafunction that will return <code>sizeof(T) &lt; sizeof(U)</code>,
  1821. there is no need to enlist a metaprogramming lambda library as in</p>
  1822. </div>
  1823. <div class="listingblock">
  1824. <div class="content">
  1825. <pre class="highlight"><code>lambda&lt;_a, _b, less&lt;sizeof_&lt;_a&gt;, sizeof_&lt;_b&gt;&gt;&gt;&gt;</code></pre>
  1826. </div>
  1827. </div>
  1828. <div class="paragraph">
  1829. <p>We could just define it inline:</p>
  1830. </div>
  1831. <div class="listingblock">
  1832. <div class="content">
  1833. <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>
  1834. </div>
  1835. </div>
  1836. </div>
  1837. </div>
  1838. <div class="sect1">
  1839. <h2 id="one_more_thing">One more thing</h2>
  1840. <div class="sectionbody">
  1841. <div class="paragraph">
  1842. <p>Finally, let me show the implementations of <code>mp_count</code> and <code>mp_count_if</code>, for
  1843. no reason other than I find them interesting. <code>mp_count&lt;L, V&gt;</code> returns the
  1844. number of occurrences of the type <code>V</code> in the list <code>L</code>; <code>mp_count_if&lt;L, P&gt;</code>
  1845. counts the number of types in <code>L</code> for which <code>P&lt;T&gt;</code> is <code>true</code>.</p>
  1846. </div>
  1847. <div class="paragraph">
  1848. <p>As a first step, I&#8217;ll implement <code>mp_plus</code>. <code>mp_plus</code> is a variadic (not just
  1849. binary) metafunction that returns the sum of its arguments.</p>
  1850. </div>
  1851. <div class="listingblock">
  1852. <div class="content">
  1853. <pre class="highlight"><code>template&lt;class... T&gt; struct mp_plus_impl;
  1854. template&lt;class... T&gt; using mp_plus = typename mp_plus_impl&lt;T...&gt;::type;
  1855. template&lt;&gt; struct mp_plus_impl&lt;&gt;
  1856. {
  1857. using type = std::integral_constant&lt;int, 0&gt;;
  1858. };
  1859. template&lt;class T1, class... T&gt; struct mp_plus_impl&lt;T1, T...&gt;
  1860. {
  1861. static constexpr auto _v = T1::value + mp_plus&lt;T...&gt;::value;
  1862. using type = std::integral_constant&lt;
  1863. typename std::remove_const&lt;decltype(_v)&gt;::type, _v&gt;;
  1864. };</code></pre>
  1865. </div>
  1866. </div>
  1867. <div class="paragraph">
  1868. <p>Now that we have <code>mp_plus</code>, <code>mp_count</code> is just</p>
  1869. </div>
  1870. <div class="listingblock">
  1871. <div class="content">
  1872. <pre class="highlight"><code>template&lt;class L, class V&gt; struct mp_count_impl;
  1873. template&lt;template&lt;class...&gt; class L, class... T, class V&gt;
  1874. struct mp_count_impl&lt;L&lt;T...&gt;, V&gt;
  1875. {
  1876. using type = mp_plus&lt;std::is_same&lt;T, V&gt;...&gt;;
  1877. };
  1878. template&lt;class L, class V&gt; using mp_count = typename mp_count_impl&lt;L, V&gt;::type;</code></pre>
  1879. </div>
  1880. </div>
  1881. <div class="paragraph">
  1882. <p>This is another illustration of the power of parameter pack expansion. It&#8217;s a
  1883. pity that we can&#8217;t use pack expansion in <code>mp_plus</code> as well, to obtain</p>
  1884. </div>
  1885. <div class="listingblock">
  1886. <div class="content">
  1887. <pre class="highlight"><code>T1::value + T2::value + T3::value + T4::value + ...</code></pre>
  1888. </div>
  1889. </div>
  1890. <div class="paragraph">
  1891. <p>directly. It would have been nice for <code>T::value + ...</code> to have been
  1892. supported, and it appears that in C&#43;&#43;17, it will be.</p>
  1893. </div>
  1894. <div class="paragraph">
  1895. <p><code>mp_count_if</code> is similarly straightforward:</p>
  1896. </div>
  1897. <div class="listingblock">
  1898. <div class="content">
  1899. <pre class="highlight"><code>template&lt;class L, template&lt;class...&gt; class P&gt; struct mp_count_if_impl;
  1900. template&lt;template&lt;class...&gt; class L, class... T, template&lt;class...&gt; class P&gt;
  1901. struct mp_count_if_impl&lt;L&lt;T...&gt;, P&gt;
  1902. {
  1903. using type = mp_plus&lt;P&lt;T&gt;...&gt;;
  1904. };
  1905. template&lt;class L, template&lt;class...&gt; class P&gt;
  1906. using mp_count_if = typename mp_count_if_impl&lt;L, P&gt;::type;</code></pre>
  1907. </div>
  1908. </div>
  1909. <div class="paragraph">
  1910. <p>at least if we require <code>P</code> to return <code>bool</code>. If not, we&#8217;ll have to coerce
  1911. <code>P&lt;T&gt;::value</code> to 0 or 1, or the count will not be correct.</p>
  1912. </div>
  1913. <div class="listingblock">
  1914. <div class="content">
  1915. <pre class="highlight"><code>template&lt;bool v&gt; using mp_bool = std::integral_constant&lt;bool, v&gt;;
  1916. template&lt;class L, template&lt;class...&gt; class P&gt; struct mp_count_if_impl;
  1917. template&lt;template&lt;class...&gt; class L, class... T, template&lt;class...&gt; class P&gt;
  1918. struct mp_count_if_impl&lt;L&lt;T...&gt;, P&gt;
  1919. {
  1920. using type = mp_plus&lt;mp_bool&lt;P&lt;T&gt;::value != 0&gt;...&gt;;
  1921. };
  1922. template&lt;class L, template&lt;class...&gt; class P&gt;
  1923. using mp_count_if = typename mp_count_if_impl&lt;L, P&gt;::type;</code></pre>
  1924. </div>
  1925. </div>
  1926. <div class="paragraph">
  1927. <p>The last primitive I&#8217;ll show is <code>mp_contains</code>. <code>mp_contains&lt;L, V&gt;</code> returns
  1928. whether the list <code>L</code> contains the type <code>V</code>:</p>
  1929. </div>
  1930. <div class="listingblock">
  1931. <div class="content">
  1932. <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>
  1933. </div>
  1934. </div>
  1935. <div class="paragraph">
  1936. <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
  1937. only interested in a boolean result&#8201;&#8212;&#8201;but it&#8217;s actually pretty competitive and
  1938. perfectly usable. We just need to add one slight optimization to <code>mp_plus</code>, the
  1939. engine behind <code>mp_count</code> and <code>mp_contains</code>:</p>
  1940. </div>
  1941. <div class="listingblock">
  1942. <div class="content">
  1943. <pre class="highlight"><code>template&lt;class T1, class T2, class T3, class T4, class T5,
  1944. class T6, class T7, class T8, class T9, class T10, class... T&gt;
  1945. struct mp_plus_impl&lt;T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...&gt;
  1946. {
  1947. static constexpr auto _v = T1::value + T2::value + T3::value + T4::value +
  1948. T5::value + T6::value + T7::value + T8::value + T9::value + T10::value +
  1949. mp_plus&lt;T...&gt;::value;
  1950. using type = std::integral_constant&lt;
  1951. typename std::remove_const&lt;decltype(_v)&gt;::type, _v&gt;;
  1952. };</code></pre>
  1953. </div>
  1954. </div>
  1955. <div class="paragraph">
  1956. <p>This cuts the number of template instantiations approximately tenfold.</p>
  1957. </div>
  1958. </div>
  1959. </div>
  1960. <div class="sect1">
  1961. <h2 id="conclusion">Conclusion</h2>
  1962. <div class="sectionbody">
  1963. <div class="paragraph">
  1964. <p>I have outlined an approach to metaprogramming in C&#43;&#43;11 that</p>
  1965. </div>
  1966. <div class="ulist">
  1967. <ul>
  1968. <li>
  1969. <p>takes advantage of variadic templates, parameter pack expansion, and template
  1970. aliases;</p>
  1971. </li>
  1972. <li>
  1973. <p>operates on any variadic template <code>L&lt;T...&gt;</code>, treating it as its
  1974. fundamental data structure, without mandating a specific type list
  1975. representation;</p>
  1976. </li>
  1977. <li>
  1978. <p>uses template aliases as its metafunctions, with the expression <code>F&lt;T...&gt;</code>
  1979. serving as the equivalent of a function call;</p>
  1980. </li>
  1981. <li>
  1982. <p>exploits the structural similarity between the data structure <code>L&lt;T...&gt;</code>
  1983. and the metafunction call <code>F&lt;T...&gt;</code>;</p>
  1984. </li>
  1985. <li>
  1986. <p>leverages parameter pack expansion as much as possible, instead of using the
  1987. traditional recursive implementations;</p>
  1988. </li>
  1989. <li>
  1990. <p>relies on inline definitions of template aliases for function composition,
  1991. instead of providing library support for this task.</p>
  1992. </li>
  1993. </ul>
  1994. </div>
  1995. </div>
  1996. </div>
  1997. <div class="sect1">
  1998. <h2 id="further_reading">Further reading</h2>
  1999. <div class="sectionbody">
  2000. <div class="paragraph">
  2001. <p><a href="simple_cxx11_metaprogramming_2.html">Part 2 is now available</a>, in which I
  2002. show algorithms that allow us to treat type lists as sets, maps, and vectors,
  2003. and demonstrate various C&#43;&#43;11 implementation techniques in the process.</p>
  2004. </div>
  2005. </div>
  2006. </div>
  2007. </div>
  2008. <div id="footer">
  2009. <div id="footer-text">
  2010. Last updated 2019-12-10 00:19:27 UTC
  2011. </div>
  2012. </div>
  2013. <style>
  2014. *:not(pre)>code { background: none; color: #600000; }
  2015. /* table tr.even, table tr.alt, table tr:nth-of-type(even) { background: none; } */
  2016. </style>
  2017. </body>
  2018. </html>