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