2017-06-07 00:02:25 +03:00
<!DOCTYPE html>
< html lang = "en" >
2017-03-14 22:57:07 +02:00
< head >
2017-06-07 00:02:25 +03:00
< meta charset = "UTF-8" >
<!-- [if IE]><meta http - equiv="X - UA - Compatible" content="IE=edge"><![endif] -->
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< meta name = "generator" content = "Asciidoctor 1.5.5" >
< meta name = "author" content = "Peter Dimov" >
2017-06-10 03:44:31 +03:00
< title > Boost.Mp11: A C++11 metaprogramming library< / title >
2017-06-07 00:02:25 +03:00
< 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" >
< style >
/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
/* Remove comment around @import statement below when using as a custom stylesheet */
/*@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";*/
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
audio,canvas,video{display:inline-block}
audio:not([controls]){display:none;height:0}
[hidden],template{display:none}
script{display:none!important}
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
a{background:transparent}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
abbr[title]{border-bottom:1px dotted}
b,strong{font-weight:bold}
dfn{font-style:italic}
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}
input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.center{margin-left:auto;margin-right:auto}
.spread{width:100%}
p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}
.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}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:none}
p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol,ul.no-bullet,ol.no-bullet{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
ul.square{list-style-type:square}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.no-bullet{list-style:none}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
abbr{text-transform:none}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
blockquote cite:before{content:"\2014 \0020"}
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
table thead,table tfoot{background:#f7f8f7;font-weight:bold}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table}
.clearfix:after,.float-group:after{clear:both}
*: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}
*:not(pre)>code.nobreak{word-wrap:normal}
*:not(pre)>code.nowrap{white-space:nowrap}
pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menu{color:rgba(0,0,0,.8)}
b.button:before,b.button:after{position:relative;top:-1px;font-weight:400}
b.button:before{content:"[";padding:0 3px 0 2px}
b.button:after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#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}
#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table}
#header:after,#content:after,#footnotes:after,#footer:after{clear:both}
#content{margin-top:1.25em}
#content:before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
#header .details{border-bottom:1px solid #ddddd8;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}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span:before{content:"\00a0\2013\00a0"}
#header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark:before{content:"\00a0|\00a0"}
#header #revnumber{text-transform:capitalize}
#header #revnumber:after{content:"\00a0"}
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}
#toc>ul{margin-left:.125em}
#toc ul.sectlevel0>li>a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media only screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}
@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2>ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#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}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
.sect1{padding-bottom:.625em}
@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}
.sect1+.sect1{border-top:1px solid #efefed}
#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}
#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}
#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}
#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}
#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}
.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
.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}
table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}
.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}
table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.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}
.exampleblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child{margin-bottom:0}
.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}
.sidebarblock>:first-child{margin-top:0}
.sidebarblock>:last-child{margin-bottom:0}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.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}
.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
.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}
.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}
.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.listingblock>.content{position:relative}
.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}
.listingblock:hover code[data-lang]:before{display:block}
.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}
.listingblock.terminal pre .command:not([data-prompt]):before{content:"$"}
table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
table.pyhltable td.code{padding-left:.75em;padding-right:0}
pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}
pre.pygments .lineno{display:inline-block;margin-right:.25em}
table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock blockquote 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}
.quoteblock blockquote{margin:0;padding:0;border:0}
.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)}
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}
.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
.quoteblock .quoteblock blockquote:before{display:none}
.verseblock{margin:0 1em 1.25em 1em}
.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}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract{margin:0 0 1.25em 0;display:block}
.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}
.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}
table.tableblock{max-width:100%;border-collapse:separate}
table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all th.tableblock,table.grid-all td.tableblock{border-width:0 1px 1px 0}
table.grid-all tfoot>tr>th.tableblock,table.grid-all tfoot>tr>td.tableblock{border-width:1px 1px 0 0}
table.grid-cols th.tableblock,table.grid-cols td.tableblock{border-width:0 1px 0 0}
table.grid-all *>tr>.tableblock:last-child,table.grid-cols *>tr>.tableblock:last-child{border-right-width:0}
table.grid-rows th.tableblock,table.grid-rows td.tableblock{border-width:0 0 1px 0}
table.grid-all tbody>tr:last-child>th.tableblock,table.grid-all tbody>tr:last-child>td.tableblock,table.grid-all thead:last-child>tr>th.tableblock,table.grid-rows tbody>tr:last-child>th.tableblock,table.grid-rows tbody>tr:last-child>td.tableblock,table.grid-rows thead:last-child>tr>th.tableblock{border-bottom-width:0}
table.grid-rows tfoot>tr>th.tableblock,table.grid-rows tfoot>tr>td.tableblock{border-width:1px 0 0 0}
table.frame-all{border-width:1px}
table.frame-sides{border-width:0 1px}
table.frame-topbot{border-width:1px 0}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock>code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
td>div.verse{white-space:pre}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.unstyled,ol.unnumbered,ul.checklist,ul.none{list-style-type:none}
ul.unstyled,ol.unnumbered,ul.checklist{margin-left:.625em}
ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1em;font-size:.85em}
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{width:1em;position:relative;top:1px}
ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}
ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}
ul.inline>li>*{display:block}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist>table tr>td:first-of-type{padding:0 .75em;line-height:1}
.colist>table tr>td:last-of-type{padding:.25em 0}
.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}
.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
.imageblock>.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
.gist .file-data>table td.line-data{width:99%}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background-color:#00fafa}
.black{color:#000}
.black-background{background-color:#000}
.blue{color:#0000bf}
.blue-background{background-color:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background-color:#fa00fa}
.gray{color:#606060}
.gray-background{background-color:#7d7d7d}
.green{color:#006000}
.green-background{background-color:#007d00}
.lime{color:#00bf00}
.lime-background{background-color:#00fa00}
.maroon{color:#600000}
.maroon-background{background-color:#7d0000}
.navy{color:#000060}
.navy-background{background-color:#00007d}
.olive{color:#606000}
.olive-background{background-color:#7d7d00}
.purple{color:#600060}
.purple-background{background-color:#7d007d}
.red{color:#bf0000}
.red-background{background-color:#fa0000}
.silver{color:#909090}
.silver-background{background-color:#bcbcbc}
.teal{color:#006060}
.teal-background{background-color:#007d7d}
.white{color:#bfbfbf}
.white-background{background-color:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background-color:#fafa00}
span.icon>.fa{cursor:default}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000}
.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}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]:after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@media print{@page{margin:1.25cm .75cm}
*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]:after{content:" (" attr(title) ")"}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}
.sect1{padding-bottom:0!important}
.sect1+.sect1{border:0!important}
#header>h1:first-child{margin-top:1.25rem}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span:before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
.listingblock code[data-lang]:before{display:block}
#footer{background:none!important;padding:0 .9375em}
#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
< / style >
2017-03-14 22:57:07 +02:00
< / head >
2017-06-07 00:02:25 +03:00
< body class = "article toc2 toc-left" >
< div id = "header" >
2017-06-10 03:44:31 +03:00
< h1 > Boost.Mp11: A C++11 metaprogramming library< / h1 >
2017-06-07 00:02:25 +03:00
< div class = "details" >
< span id = "author" class = "author" > Peter Dimov< / span > < br >
< / div >
< div id = "toc" class = "toc2" >
< div id = "toctitle" > Table of Contents< / div >
< ul class = "sectlevel1" >
< li > < a href = "#overview" > Overview< / a > < / li >
< li > < a href = "#definitions" > Definitions< / a > < / li >
< li > < a href = "#examples" > Examples< / a >
< ul class = "sectlevel2" >
< li > < a href = "#generating_test_cases" > Generating Test Cases< / a > < / li >
2017-06-10 03:44:31 +03:00
< li > < a href = "#writing_common_type_specializations" > Writing common_type Specializations< / a > < / li >
< li > < a href = "#fixing_tuple_cat" > Fixing tuple_cat< / a > < / li >
2017-06-07 00:02:25 +03:00
< li > < a href = "#computing_return_types" > Computing Return Types< / a > < / li >
< / ul >
< / li >
< li > < a href = "#reference" > Reference< / a >
< ul class = "sectlevel2" >
< li > < a href = "#integral" > Integral Constants, < boost/mp11/integral.hpp> < / a >
< ul class = "sectlevel3" >
< li > < a href = "#mp_bool_b" > mp_bool< B> < / a > < / li >
< li > < a href = "#mp_true" > mp_true< / a > < / li >
< li > < a href = "#mp_false" > mp_false< / a > < / li >
< li > < a href = "#mp_to_bool_t" > mp_to_bool< T> < / a > < / li >
< li > < a href = "#mp_not_t" > mp_not< T> < / a > < / li >
< li > < a href = "#mp_int_i" > mp_int< I> < / a > < / li >
< li > < a href = "#mp_size_t_n" > mp_size_t< N> < / a > < / li >
< / ul >
< / li >
< li > < a href = "#list" > List Operations, < boost/mp11/list.hpp> < / a >
< ul class = "sectlevel3" >
< li > < a href = "#mp_list_t" > mp_list< T… ​ > < / a > < / li >
< li > < a href = "#mp_size_l" > mp_size< L> < / a > < / li >
< li > < a href = "#mp_empty_l" > mp_empty< L> < / a > < / li >
< li > < a href = "#mp_front_l" > mp_front< L> < / a > < / li >
< li > < a href = "#mp_pop_front_l" > mp_pop_front< L> < / a > < / li >
< li > < a href = "#mp_first_l" > mp_first< L> < / a > < / li >
< li > < a href = "#mp_rest_l" > mp_rest< L> < / a > < / li >
< li > < a href = "#mp_second_l" > mp_second< L> < / a > < / li >
< li > < a href = "#mp_third_l" > mp_third< L> < / a > < / li >
< li > < a href = "#mp_push_front_l_t" > mp_push_front< L, T… ​ > < / a > < / li >
< li > < a href = "#mp_push_back_l_t" > mp_push_back< L, T… ​ > < / a > < / li >
< li > < a href = "#mp_rename_l_y" > mp_rename< L, Y> < / a > < / li >
< li > < a href = "#mp_apply_f_l" > mp_apply< F, L> < / a > < / li >
< li > < a href = "#mp_apply_q_q_l" > mp_apply_q< Q, L> < / a > < / li >
< li > < a href = "#mp_append_l" > mp_append< L… ​ > < / a > < / li >
< li > < a href = "#mp_replace_front_l_t" > mp_replace_front< L, T> < / a > < / li >
< li > < a href = "#mp_replace_first_l_t" > mp_replace_first< L, T> < / a > < / li >
< li > < a href = "#mp_replace_second_l_t" > mp_replace_second< L, T> < / a > < / li >
< li > < a href = "#mp_replace_third_l_t" > mp_replace_third< L, T> < / a > < / li >
< / ul >
< / li >
< li > < a href = "#utility" > Utility Components, < boost/mp11/utility.hpp> < / a >
< ul class = "sectlevel3" >
< li > < a href = "#mp_identity_t" > mp_identity< T> < / a > < / li >
< li > < a href = "#mp_identity_t_t" > mp_identity_t< T> < / a > < / li >
< li > < a href = "#mp_inherit_t" > mp_inherit< T… ​ > < / a > < / li >
< li > < a href = "#mp_if_c_c_t_e" > mp_if_c< C, T, E… ​ > < / a > < / li >
< li > < a href = "#mp_if_c_t_e" > mp_if< C, T, E… ​ > < / a > < / li >
< li > < a href = "#mp_eval_if_c_c_t_f_u" > mp_eval_if_c< C, T, F, U… ​ > < / a > < / li >
< li > < a href = "#mp_eval_if_c_t_f_u" > mp_eval_if< C, T, F, U… ​ > < / a > < / li >
< li > < a href = "#mp_eval_if_q_c_t_q_u" > mp_eval_if_q< C, T, Q, U… ​ > < / a > < / li >
< li > < a href = "#mp_valid_f_t" > mp_valid< F, T… ​ > < / a > < / li >
< li > < a href = "#mp_defer_f_t" > mp_defer< F, T… ​ > < / a > < / li >
< li > < a href = "#mp_quote_f" > mp_quote< F> < / a > < / li >
< li > < a href = "#mp_invoke_q_t" > mp_invoke< Q, T… ​ > < / a > < / li >
< / ul >
< / li >
< li > < a href = "#algorithm" > Algorithms, < boost/mp11/algorithm.hpp> < / a >
< ul class = "sectlevel3" >
< li > < a href = "#mp_assign_l1_l2" > mp_assign< L1, L2> < / a > < / li >
< li > < a href = "#mp_clear_l" > mp_clear< L> < / a > < / li >
< li > < a href = "#mp_transform_f_l" > mp_transform< F, L… ​ > < / a > < / li >
< li > < a href = "#mp_transform_q_q_l" > mp_transform_q< Q, L… ​ > < / a > < / li >
< li > < a href = "#mp_transform_if_p_f_l" > mp_transform_if< P, F, L… ​ > < / a > < / li >
< li > < a href = "#mp_transform_if_q_qp_qf_l" > mp_transform_if_q< Qp, Qf, L… ​ > < / a > < / li >
< li > < a href = "#mp_fill_l_v" > mp_fill< L, V> < / a > < / li >
< li > < a href = "#mp_count_l_v" > mp_count< L, V> < / a > < / li >
< li > < a href = "#mp_count_if_l_p" > mp_count_if< L, P> < / a > < / li >
< li > < a href = "#mp_contains_l_v" > mp_contains< L, V> < / a > < / li >
< li > < a href = "#mp_repeat_c_l_n" > mp_repeat_c< L, N> < / a > < / li >
< li > < a href = "#mp_repeat_l_n" > mp_repeat< L, N> < / a > < / li >
< li > < a href = "#mp_product_f_l" > mp_product< F, L… ​ > < / a > < / li >
< li > < a href = "#mp_product_q_q_l" > mp_product_q< Q, L… ​ > < / a > < / li >
< li > < a href = "#mp_drop_c_l_n" > mp_drop_c< L, N> < / a > < / li >
< li > < a href = "#mp_drop_l_n" > mp_drop< L, N> < / a > < / li >
< li > < a href = "#mp_iota_c_n" > mp_iota_c< N> < / a > < / li >
< li > < a href = "#mp_iota_n" > mp_iota< N> < / a > < / li >
< li > < a href = "#mp_at_c_l_i" > mp_at_c< L, I> < / a > < / li >
< li > < a href = "#mp_at_l_i" > mp_at< L, I> < / a > < / li >
< li > < a href = "#mp_take_c_l_n" > mp_take_c< L, N> < / a > < / li >
< li > < a href = "#mp_take_l_n" > mp_take< L, N> < / a > < / li >
< li > < a href = "#mp_insert_c_l_i_t" > mp_insert_c< L, I, T… ​ > < / a > < / li >
< li > < a href = "#mp_insert_l_i_t" > mp_insert< L, I, T… ​ > < / a > < / li >
< li > < a href = "#mp_erase_c_l_i_j" > mp_erase_c< L, I, J> < / a > < / li >
< li > < a href = "#mp_erase_l_i_j" > mp_erase< L, I, J> < / a > < / li >
< li > < a href = "#mp_replace_l_v_w" > mp_replace< L, V, W> < / a > < / li >
< li > < a href = "#mp_replace_if_l_p_w" > mp_replace_if< L, P, W> < / a > < / li >
< li > < a href = "#mp_replace_at_c_l_i_w" > mp_replace_at_c< L, I, W> < / a > < / li >
< li > < a href = "#mp_replace_at_l_i_w" > mp_replace_at< L, I, W> < / a > < / li >
< li > < a href = "#mp_copy_if_l_p" > mp_copy_if< L, P> < / a > < / li >
< li > < a href = "#mp_remove_l_v" > mp_remove< L, V> < / a > < / li >
< li > < a href = "#mp_remove_if_l_p" > mp_remove_if< L, P> < / a > < / li >
< li > < a href = "#mp_partition_l_p" > mp_partition< L, P> < / a > < / li >
< li > < a href = "#mp_sort_l_p" > mp_sort< L, P> < / a > < / li >
< li > < a href = "#mp_find_l_v" > mp_find< L, V> < / a > < / li >
< li > < a href = "#mp_find_if_l_p" > mp_find_if< L, P> < / a > < / li >
< li > < a href = "#mp_reverse_l" > mp_reverse< L> < / a > < / li >
< li > < a href = "#mp_fold_l_v_f" > mp_fold< L, V, F> < / a > < / li >
< li > < a href = "#mp_reverse_fold_l_v_f" > mp_reverse_fold< L, V, F> < / a > < / li >
< li > < a href = "#mp_unique_l" > mp_unique< L> < / a > < / li >
< li > < a href = "#mp_all_of_l_p" > mp_all_of< L, P> < / a > < / li >
< li > < a href = "#mp_none_of_l_p" > mp_none_of< L, P> < / a > < / li >
< li > < a href = "#mp_any_of_l_p" > mp_any_of< L, P> < / a > < / li >
< li > < a href = "#mp_for_each_l_f" > mp_for_each< L> (f)< / a > < / li >
< li > < a href = "#mp_with_index_n_i_f" > mp_with_index< N> (i, f)< / a > < / li >
< / ul >
< / li >
< li > < a href = "#set" > Set Operations, < boost/mp11/set.hpp> < / a >
< ul class = "sectlevel3" >
< li > < a href = "#mp_set_contains_s_v" > mp_set_contains< S, V> < / a > < / li >
< li > < a href = "#mp_set_push_back_s_t" > mp_set_push_back< S, T… ​ > < / a > < / li >
< li > < a href = "#mp_set_push_front_s_t" > mp_set_push_front< S, T… ​ > < / a > < / li >
< / ul >
< / li >
< li > < a href = "#map" > Map Operations, < boost/mp11/map.hpp> < / a >
< ul class = "sectlevel3" >
< li > < a href = "#mp_map_find_m_k" > mp_map_find< M, K> < / a > < / li >
< li > < a href = "#mp_map_contains_m_k" > mp_map_contains< M, K> < / a > < / li >
< li > < a href = "#mp_map_insert_m_t" > mp_map_insert< M, T> < / a > < / li >
< li > < a href = "#mp_map_replace_m_t" > mp_map_replace< M, T> < / a > < / li >
< li > < a href = "#mp_map_update_m_t_f" > mp_map_update< M, T, F> < / a > < / li >
< li > < a href = "#mp_map_erase_m_k" > mp_map_erase< M, K> < / a > < / li >
< / ul >
< / li >
< li > < a href = "#function" > Helper Metafunctions, < boost/mp11/function.hpp> < / a >
< ul class = "sectlevel3" >
< li > < a href = "#mp_void_t" > mp_void< T… ​ > < / a > < / li >
< li > < a href = "#mp_and_t" > mp_and< T… ​ > < / a > < / li >
< li > < a href = "#mp_all_t" > mp_all< T… ​ > < / a > < / li >
< li > < a href = "#mp_or_t" > mp_or< T… ​ > < / a > < / li >
< li > < a href = "#mp_any_t" > mp_any< T… ​ > < / a > < / li >
< li > < a href = "#mp_same_t" > mp_same< T… ​ > < / a > < / li >
< li > < a href = "#mp_plus_t" > mp_plus< T… ​ > < / a > < / li >
< / ul >
< / li >
< li > < a href = "#bind" > Bind, < boost/mp11/bind.hpp> < / a >
< ul class = "sectlevel3" >
< li > < a href = "#mp_arg_i" > mp_arg< I> < / a > < / li >
< li > < a href = "#1_9" > _1, … ​ , _9< / a > < / li >
< li > < a href = "#mp_bind_f_t" > mp_bind< F, T… ​ > < / a > < / li >
< li > < a href = "#mp_bind_q_q_t" > mp_bind_q< Q, T… ​ > < / a > < / li >
< li > < a href = "#mp_bind_front_f_t" > mp_bind_front< F, T… ​ > < / a > < / li >
< li > < a href = "#mp_bind_front_q_q_t" > mp_bind_front_q< Q, T… ​ > < / a > < / li >
< li > < a href = "#mp_bind_back_f_t" > mp_bind_back< F, T… ​ > < / a > < / li >
< li > < a href = "#mp_bind_back_q_q_t" > mp_bind_back_q< Q, T… ​ > < / a > < / li >
< / ul >
< / li >
< li > < a href = "#integer_sequence" > Integer Sequences, < boost/mp11/integer_sequence.hpp> < / a >
< ul class = "sectlevel3" >
< li > < a href = "#integer_sequence_t_i" > integer_sequence< T, I… ​ > < / a > < / li >
< li > < a href = "#make_integer_sequence_t_n" > make_integer_sequence< T, N> < / a > < / li >
< li > < a href = "#index_sequence_i" > index_sequence< I… ​ > < / a > < / li >
< li > < a href = "#make_index_sequence_n" > make_index_sequence< N> < / a > < / li >
< li > < a href = "#index_sequence_for_t" > index_sequence_for< T… ​ > < / a > < / li >
< / ul >
< / li >
2017-06-08 16:35:55 +03:00
< li > < a href = "#tuple" > Tuple Operations, < boost/mp11/tuple.hpp> < / a >
2017-06-07 00:02:25 +03:00
< ul class = "sectlevel3" >
2017-06-08 17:19:28 +03:00
< li > < a href = "#tuple_apply_f_tp" > tuple_apply(f, tp)< / a > < / li >
2017-06-08 19:22:53 +03:00
< li > < a href = "#construct_from_tuple_t_tp" > construct_from_tuple< T> (tp)< / a > < / li >
2017-06-07 00:02:25 +03:00
< li > < a href = "#tuple_for_each_tp_f" > tuple_for_each(tp, f)< / a > < / li >
< / ul >
< / li >
< / ul >
< / li >
< li > < a href = "#copyright_and_license" > Appendix A: Copyright and License< / a > < / li >
< / ul >
< / div >
< / div >
< div id = "content" >
< div class = "sect1" >
< h2 id = "overview" > Overview< / h2 >
< div class = "sectionbody" >
< div class = "paragraph" >
2017-06-10 03:44:31 +03:00
< p > Mp11 is a C++11 metaprogramming library for compile-time manipulation of data structures
that contain types. It’ s based on template aliases and variadic templates and implements the
approach outlined in the article
2017-06-07 00:02:25 +03:00
< a href = "http://pdimov.com/cpp2/simple_cxx11_metaprogramming.html" > "Simple C++ metaprogramming"< / a >
and < a href = "http://pdimov.com/cpp2/simple_cxx11_metaprogramming_2.html" > its sequel< / a > . Reading these
2017-06-07 00:39:45 +03:00
articles before proceeding with this documentation is < em > highly< / em > recommended.< / p >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "paragraph" >
< p > The general principles upon which Mp11 is built are that algorithms and metafunctions are
template aliases of the form < code > F< T… ​ > < / code > and data structures are lists of the form < code > L< T… ​ > < / code > ,
with the library placing no requirements on < code > L< / code > . < code > mp_list< T… ​ > < / code > is the built-in list type,
but < code > std::tuple< T… ​ > < / code > , < code > std::pair< T1, T2> < / code > and < code > std::variant< T… ​ > < / code > are also perfectly
legitimate list types, although of course < code > std::pair< T1, T2> < / code > , due to having exactly two elements,
is not resizeable and will consequently not work with algorithms that need to add or remove
elements.< / p >
< / div >
< div class = "paragraph" >
< p > Another distinguishing feature of this approach is that lists (< code > L< T… ​ > < / code > ) have the same form as
metafunctions (< code > F< T… ​ > < / code > ) and can therefore be used as such. For example, applying < code > std::add_pointer_t< / code >
to the list < code > std::tuple< int, float> < / code > by way of < code > mp_transform< std::add_pointer_t, std::tuple< int, float> > < / code >
gives us < code > std::tuple< int*, float*> < / code > , but we can also apply < code > mp_list< / code > to the same tuple:< / p >
< / div >
< div class = "literalblock" >
< div class = "content" >
< pre > using R = mp_transform< mp_list, std::tuple< int, float> > ;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > and get < code > std::tuple< mp_list< int> , mp_list< float> > < / code > .< / p >
< / div >
< / div >
< / div >
< div class = "sect1" >
< h2 id = "definitions" > Definitions< / h2 >
< div class = "sectionbody" >
< div class = "paragraph" >
< p > A < em > list< / em > is a  —   usually but not necessarily variadic  —   template class whose parameters are all types,
for example < code > mp_list< char[], void> < / code > , < code > mp_list< > < / code > , < code > std::tuple< int, float, char> < / code > , < code > std::pair< int, float> < / code > , < code > std::shared_ptr< X> < / code > .< / p >
< / div >
< div class = "paragraph" >
< p > A < em > metafunction< / em > is a class template or a template alias whose parameters are all types, for example < code > std::add_pointer_t< / code > ,
< code > std::is_const< / code > , < code > mp_second< / code > , < code > mp_push_front< / code > , < code > mp_list< / code > , < code > std::tuple< / code > , < code > std::pair< / code > , < code > std::shared_ptr< / code > , or< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > template< class...> using F1 = void;
2017-06-07 00:02:25 +03:00
template< class T> using F2 = T*;
2017-06-10 03:44:31 +03:00
template< class... T> using F3 = std::integral_constant< std::size_t, sizeof...(T)> ;< / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > A < em > quoted metafunction< / em > is a class with a public metafunction member called < code > fn< / code > , for example< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > struct Q1 { template< class...> using fn = void; };
2017-06-07 00:02:25 +03:00
struct Q2 { template< class T> using fn = T*; };
2017-06-10 03:44:31 +03:00
struct Q3 { template< class... T> using fn =
std::integral_constant< std::size_t, sizeof...(T)> ; };< / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > An < em > integral constant type< / em > is a class with a public member < code > value< / code > that is an integral constant in the C++ sense. For example,
< code > std::integral_constant< int, 7> < / code > , or< / p >
< / div >
< div class = "literalblock" >
< div class = "content" >
< pre > struct N { static int constexpr value = 2; };< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > A < em > set< / em > is a list whose elements are unique.< / p >
< / div >
< div class = "paragraph" >
< p > A < em > map< / em > is a list of lists, the inner lists having at least one element (the key.) The keys of the map must be unique. For example,< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using M1 = std::tuple< std::pair< int, int*> , std::pair< float, float*> ,
std::pair< void, void*> > ;
using M2 = mp_list< mp_list< int, int*> , mp_list< float> ,
mp_list< char, char[1], char[2]> > ;< / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< / div >
< div class = "sect1" >
< h2 id = "examples" > Examples< / h2 >
< div class = "sectionbody" >
< div class = "sect2" >
< h3 id = "generating_test_cases" > Generating Test Cases< / h3 >
< div class = "paragraph" >
< p > Let’ s suppose that we have written a metafunction < code > result< T, U> < / code > :< / p >
< / div >
< div class = "listingblock" >
< div class = "content" >
< pre class = "highlight" > < code > template< class T> using promote = typename std::common_type< T, int> ::type;
2017-05-19 02:43:47 +03:00
2017-06-07 00:02:25 +03:00
template< class T, class U> using result =
typename std::common_type< promote< T> , promote< U> > ::type;< / code > < / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > that ought to represent the result of an arithmetic operation on the integer types < code > T< / code > and < code > U< / code > ,
for example < code > t + u< / code > . We want to test whether < code > result< T, U> < / code > gives correct results for various combinations
of < code > T< / code > and < code > U< / code > , so we write the function< / p >
< / div >
< div class = "listingblock" >
< div class = "content" >
< pre class = "highlight" > < code > template< class T1, class T2> void test_result()
{
using T3 = decltype( T1() + T2() );
using T4 = result< T1, T2> ;
2017-05-19 02:43:47 +03:00
2017-06-07 00:02:25 +03:00
std::cout < < ( std::is_same< T3, T4> ::value? "[PASS]": "[FAIL]" ) < < std::endl;
}< / code > < / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > and then need to call it a substantial number of times:< / p >
< / div >
< div class = "literalblock" >
< div class = "content" >
< pre > int main()
{
test_result< char, char> ();
test_result< char, short> ();
test_result< char, int> ();
test_result< char, unsigned> ();
// ...
}< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Writing all those type combinations by hand is unwieldy, error prone, and worst of all, boring. This is
how we can leverage Mp11 to automate the task:< / p >
< / div >
< div class = "listingblock" >
< div class = "content" >
< pre class = "highlight" > < code > #include < boost/mp11.hpp>
#include < boost/core/demangle.hpp>
#include < type_traits>
#include < iostream>
#include < typeinfo>
2017-05-19 02:43:47 +03:00
2017-06-07 00:02:25 +03:00
using namespace boost::mp11;
2017-05-19 02:43:47 +03:00
2017-06-07 00:02:25 +03:00
template< class T> std::string name()
{
return boost::core::demangle( typeid(T).name() );
}
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
template< class T> using promote = typename std::common_type< T, int> ::type;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
template< class T, class U> using result =
typename std::common_type< promote< T> , promote< U> > ::type;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
template< class T1, class T2> void test_result( mp_list< T1, T2> const& )
{
using T3 = decltype( T1() + T2() );
using T4 = result< T1, T2> ;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
std::cout < < ( std::is_same< T3, T4> ::value? "[PASS] ": "[FAIL] " )
< < name< T1> () < < " + " < < name< T2> () < < " -> " < < name< T3> ()
< < ", result: " < < name< T4> () < < std::endl;
}
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
int main()
{
using L = std::tuple< char, short, int, unsigned, long, unsigned long> ;
tuple_for_each( mp_product< mp_list, L, L> (), [](auto& & x){ test_result(x); } );
}< / code > < / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > How does it work?< / p >
< / div >
< div class = "paragraph" >
< p > < code > mp_product< F, L1, L2> < / code > calls < code > F< T1, T2> < / code > where < code > T1< / code > varies over the elements of < code > L1< / code > and < code > T2< / code > varies over
the elements of < code > L2< / code > , as if by executing two nested loops. It then returns a list of these results, of the same
type as < code > L1< / code > .< / p >
< / div >
< div class = "paragraph" >
< p > In our case, both lists are the same < code > std::tuple< / code > , and < code > F< / code > is < code > mp_list< / code > , so < code > mp_product< mp_list, L, L> < / code > will get us
< code > std::tuple< mp_list< char, char> , mp_list< char, short> , mp_list< char, int> , … ​ , mp_list< unsigned long, long> , mp_list< unsigned long, unsigned long> > < / code > .< / p >
< / div >
< div class = "paragraph" >
< p > We then default-construct this tuple and pass it to < code > tuple_for_each< / code > . < code > tuple_for_each(tp, f)< / code > calls < code > f< / code > for every
tuple element; we use a (C++14) lambda that calls < code > test_result< / code > .< / p >
< / div >
< div class = "paragraph" >
< p > In pure C++11, we can’ t use a lambda with an < code > auto& & < / code > parameter, so we’ ll have to make < code > test_result< / code > a function object with
a templated < code > operator()< / code > and pass that to < code > tuple_for_each< / code > directly:< / p >
< / div >
< div class = "listingblock" >
< div class = "content" >
< pre class = "highlight" > < code > struct test_result
{
template< class T1, class T2> void operator()( mp_list< T1, T2> const& ) const
{
using T3 = decltype( T1() + T2() );
using T4 = result< T1, T2> ;
std::cout < < ( std::is_same< T3, T4> ::value? "[PASS] ": "[FAIL] " )
< < name< T1> () < < " + " < < name< T2> () < < " -> " < < name< T3> ()
< < ", result: " < < name< T4> () < < std::endl;
}
};
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
int main()
{
using L = std::tuple< char, short, int, unsigned, long, unsigned long> ;
tuple_for_each( mp_product< mp_list, L, L> (), test_result() );
}< / code > < / pre >
< / div >
< / div >
< / div >
< div class = "sect2" >
2017-06-10 03:44:31 +03:00
< h3 id = "writing_common_type_specializations" > Writing common_type Specializations< / h3 >
2017-06-07 00:02:25 +03:00
< div class = "paragraph" >
< p > The standard trait < code > std::common_type< / code > , used to obtain a type to which all of its arguments can convert without
unnecessary loss of precision, can be user-specialized when its default implementation (based on the ternary < code > ?:< / code >
operator) is unsuitable.< / p >
< / div >
< div class = "paragraph" >
< p > Let’ s write a < code > common_type< / code > specialization for two < code > std::tuple< / code > arguments. For that, we need a metafunction that
applies < code > std::common_type< / code > to each pair of elements and gathers the results into a tuple:< / p >
< / div >
< div class = "listingblock" >
< div class = "content" >
< pre class = "highlight" > < code > template< class... T> using common_type_t =
typename std::common_type< T...> ::type; // standard in C++14
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
template< class Tp1, class Tp2> using common_tuple =
mp_transform< common_type_t, Tp1, Tp2> ;< / code > < / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > then specialize < code > common_type< / code > to use it:< / p >
< / div >
< div class = "listingblock" >
< div class = "content" >
< pre class = "highlight" > < code > namespace std
{
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
template< class... T1, class... T2>
struct common_type< std::tuple< T1...> , std::tuple< T2...> > :
mp_defer< common_tuple, std::tuple< T1...> , std::tuple< T2...> >
{
};
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
} // std< / code > < / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > (There is no need to specialize < code > std::common_type< / code > for more than two arguments - it takes care of synthesizing the appropriate semantics from
the binary case.)< / p >
< / div >
< div class = "paragraph" >
< p > The subtlety here is the use of < code > mp_defer< / code > . We could have defined a nested < code > type< / code > to < code > common_tuple< std::tuple< T1… ​ > , std::tuple< T2… ​ > > < / code > ,
and it would still have worked in all valid cases. By letting < code > mp_defer< / code > define < code > type< / code > , though, we make our specialization < em > SFINAE-friendly< / em > .< / p >
< / div >
< div class = "paragraph" >
< p > That is, when our < code > common_tuple< / code > causes a substitution failure instead of a hard error, < code > mp_defer< / code > will not define a nested < code > type< / code > ,
and < code > common_type_t< / code > , which is defined as < code > typename common_type< … ​ > ::type< / code > , will also cause a substitution failure.< / p >
< / div >
< div class = "paragraph" >
< p > As another example, consider the hypothetical type < code > expected< T, E… ​ > < / code > that represents either a successful return with a value of < code > T< / code > ,
or an unsucessful return with an error code of some type in the list < code > E… ​ < / code > . The common type of < code > expected< T1, E1, E2, E3> < / code > and
< code > expected< T2, E1, E4, E5> < / code > is < code > expected< common_type_t< T1, T2> , E1, E2, E3, E4, E5> < / code > . That is, the possible return values are
combined into their common type, and we take the union of the set of error types.< / p >
< / div >
< div class = "paragraph" >
< p > Therefore,< / p >
< / div >
< div class = "listingblock" >
< div class = "content" >
< pre class = "highlight" > < code > template< class T1, class E1, class T2, class E2> using common_expected =
2017-06-10 03:44:31 +03:00
mp_rename< mp_push_front< mp_unique< mp_append< E1, E2> > , common_type_t< T1, T2> > ,
expected> ;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
namespace std
{
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
template< class T1, class... E1, class T2, class... E2>
struct common_type< expected< T1, E1...> , expected< T2, E2...> > :
mp_defer< common_expected, T1, mp_list< E1...> , T2, mp_list< E2...> >
{
};
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
} // std< / code > < / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Here we’ ve taken a different tack; instead of passing the < code > expected< / code > types to < code > common_expected< / code > , we’ re passing the < code > T< / code > types and lists of
the < code > E< / code > types. This makes our job easier. < code > mp_unique< mp_append< E1, E2> > < / code > gives us the concatenation of < code > E1< / code > and < code > E2< / code > with the duplicates
removed; we then add < code > common_type_t< T1, T2> < / code > to the front via < code > mp_push_front< / code > ; and finally, we < code > mp_rename< / code > the resultant < code > mp_list< / code >
to < code > expected< / code > .< / p >
< / div >
< / div >
< div class = "sect2" >
2017-06-10 03:44:31 +03:00
< h3 id = "fixing_tuple_cat" > Fixing tuple_cat< / h3 >
2017-06-07 00:02:25 +03:00
< div class = "paragraph" >
< p > The article < a href = "http://pdimov.com/cpp2/simple_cxx11_metaprogramming.html#" > Simple C++11 metaprogramming< / a > builds an
implementation of the standard function < code > tuple_cat< / code > , with the end result given below:< / p >
< / div >
< div class = "listingblock" >
< div class = "content" >
< pre class = "highlight" > < code > template< class L> using F = mp_iota< mp_size< L> > ;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
template< class R, class...Is, class... Ks, class Tp>
R tuple_cat_( mp_list< Is...> , mp_list< Ks...> , Tp tp )
{
return R{ std::get< Ks::value> (std::get< Is::value> (tp))... };
}
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
template< class... Tp,
class R = mp_append< std::tuple< > , typename std::remove_reference< Tp> ::type...> >
R tuple_cat( Tp & & ... tp )
{
std::size_t const N = sizeof...(Tp);
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
// inner
2017-05-17 20:47:25 +03:00
2017-06-10 03:44:31 +03:00
using list1 = mp_list<
mp_rename< typename std::remove_reference< Tp> ::type, mp_list> ...> ;
2017-06-07 00:02:25 +03:00
using list2 = mp_iota_c< N> ;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
using list3 = mp_transform< mp_fill, list1, list2> ;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
using inner = mp_apply< mp_append, list3> ;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
// outer
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
using list4 = mp_transform< F, list1> ;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
using outer = mp_apply< mp_append, list4> ;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
//
2017-05-17 20:47:25 +03:00
2017-06-10 03:44:31 +03:00
return tuple_cat_< R> ( inner(), outer(),
std::forward_as_tuple( std::forward< Tp> (tp)... ) );
2017-06-07 00:02:25 +03:00
}< / code > < / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > This function, however, is not entirely correct, in that it doesn’ t handle some cases properly. For example,
trying to concatenate tuples containing move-only elements such as < code > unique_ptr< / code > fails:< / p >
< / div >
< div class = "listingblock" >
< div class = "content" >
< pre class = "highlight" > < code > std::tuple< std::unique_ptr< int> > t1;
std::tuple< std::unique_ptr< float> > t2;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
auto result = ::tuple_cat( std::move( t1 ), std::move( t2 ) );< / code > < / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Trying to concatenate < code > const< / code > tuples fails:< / p >
< / div >
< div class = "listingblock" >
< div class = "content" >
< pre class = "highlight" > < code > std::tuple< int> const t1;
std::tuple< float> const t2;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
auto result = ::tuple_cat( t1, t2 );< / code > < / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > And finally, the standard < code > tuple_cat< / code > is specified to work on arbitrary tuple-like types (that is, all types
that support < code > tuple_size< / code > , < code > tuple_element< / code > , and < code > get< / code > ), while our implementation only works with < code > tuple< / code > and
< code > pair< / code > . < code > std::array< / code > , for example, fails:< / p >
< / div >
< div class = "listingblock" >
< div class = "content" >
< pre class = "highlight" > < code > std::array< int, 2> t1{ 1, 2 };
std::array< float, 3> t2{ 3.0f, 4.0f, 5.0f };
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
auto result = ::tuple_cat( t1, t2 );< / code > < / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Let’ s fix these one by one. Support for move-only types is easy, if one knows where to look. The problem is
that < code > Tp< / code > that we’ re passing to the helper < code > tuple_cat_< / code > is (correctly) < code > tuple< unique_ptr< int> & & , unique_ptr< float> & & > < / code > ,
but < code > std::get< 0> (tp)< / code > still returns < code > unique_ptr< int> & < / code > , because < code > tp< / code > is an lvalue. This behavior is a bit
2017-06-10 03:44:31 +03:00
surprising, but is intended to prevent inadvertent double moves.< / p >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "paragraph" >
< p > Long story short, we need < code > std::move(tp)< / code > in < code > tuple_cat_< / code > to make < code > tp< / code > an rvalue:< / p >
< / div >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class R, class...Is, class... Ks, class Tp>
R tuple_cat_( mp_list< Is...> , mp_list< Ks...> , Tp tp )
{
return R{ std::get< Ks::value> (std::get< Is::value> (std::move(tp)))... };
}< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Next, < code > const< / code > -qualified tuples. The issue here is that we’ re stripping references from the input tuples, but not
< code > const< / code > . As a result, we’ re trying to manipulate types such as < code > tuple< int> const< / code > with Mp11 algorithms, and these
types do not fit the list concept. We just need to strip qualifiers as well, by defining the useful < code > remove_cv_ref< / code >
primitive that is inexplicably missing from the standard library:< / p >
< / div >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class T> using remove_cv_ref = typename std::remove_cv<
typename std::remove_reference< T> ::type> ::type;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > and then by using < code > remove_cv_ref< Tp> < / code > in place of < code > typename std::remove_reference< Tp> ::type< / code > :< / p >
< / div >
< div class = "listingblock" >
< div class = "content" >
< pre class = "highlight" > < code > template< class... Tp,
class R = mp_append< std::tuple< > , remove_cv_ref< Tp> ...> >
R tuple_cat( Tp & & ... tp )
{
std::size_t const N = sizeof...(Tp);
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
// inner
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
using list1 = mp_list< mp_rename< remove_cv_ref< Tp> , mp_list> ...> ;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
// ...< / code > < / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Finally, tuple-like types. We’ ve so far exploited the fact that < code > std::pair< / code > and < code > std::tuple< / code > are valid Mp11 lists,
but in general, arbitrary tuple-like types aren’ t, so we need to convert them into such. For that, we’ ll need to
define a metafunction < code > from_tuple_like< / code > that will take an arbitrary tuple-like type and will return, in our case,
the corresponding < code > mp_list< / code > .< / p >
< / div >
< div class = "paragraph" >
< p > Technically, a more principled approach would’ ve been to return < code > std::tuple< / code > , but here < code > mp_list< / code > will prove more
convenient.< / p >
< / div >
< div class = "paragraph" >
< p > What we need is, given a tuple-like type < code > Tp< / code > , to obtain < code > mp_list< std::tuple_element< 0, Tp> ::type, std::tuple_element< 1, Tp> ::type,
… ​ , std::tuple_element< N-1, Tp> ::type> < / code > , where < code > N< / code > is < code > tuple_size< Tp> ::value< / code > . Here’ s one way to do it:< / p >
< / div >
< div class = "listingblock" >
< div class = "content" >
< pre class = "highlight" > < code > template< class T, class I> using tuple_element =
typename std::tuple_element< I::value, T> ::type;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
template< class T> using from_tuple_like =
mp_product< tuple_element, mp_list< T> , mp_iota< std::tuple_size< T> > > ;< / code > < / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > (< code > mp_iota< N> < / code > is an algorithm that returns an < code > mp_list< / code > with elements < code > mp_size_t< 0> < / code > , < code > mp_size_t< 1> < / code > , … ​ , < code > mp_size_t< N-1> < / code > .)< / p >
< / div >
< div class = "paragraph" >
< p > Remember that < code > mp_product< F, L1, L2> < / code > performs the equivalent of two nested loops over the elements of < code > L1< / code > and < code > L2< / code > ,
applying < code > F< / code > to the two variables and gathering the result. In our case < code > L1< / code > consists of the single element < code > T< / code > , so
only the second loop (over < code > mp_iota< N> < / code > , where < code > N< / code > is < code > tuple_size< T> < / code > ), remains, and we get a list of the same type
as < code > L1< / code > (an < code > mp_list< / code > ) with contents < code > tuple_element< T, mp_size_t< 0> > < / code > , < code > tuple_element< T, mp_size_t< 1> > < / code > , … ​ ,
< code > tuple_element< T, mp_size_t< N-1> > < / code > .< / p >
< / div >
< div class = "paragraph" >
< p > For completeness’ s sake, here’ s another, more traditional way to achieve the same result:< / p >
< / div >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class T> using from_tuple_like =
mp_transform_q< mp_bind_front< tuple_element, T> , mp_iota< std::tuple_size< T> > > ;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > With all these fixes applied, our fully operational < code > tuple_cat< / code > now looks like this:< / p >
< / div >
< div class = "listingblock" >
< div class = "content" >
< pre class = "highlight" > < code > template< class L> using F = mp_iota< mp_size< L> > ;
2017-03-17 05:55:27 +02:00
2017-06-07 00:02:25 +03:00
template< class R, class...Is, class... Ks, class Tp>
R tuple_cat_( mp_list< Is...> , mp_list< Ks...> , Tp tp )
{
return R{ std::get< Ks::value> (std::get< Is::value> (std::move(tp)))... };
}
2017-03-17 05:55:27 +02:00
2017-06-07 00:02:25 +03:00
template< class T> using remove_cv_ref = typename std::remove_cv<
typename std::remove_reference< T> ::type> ::type;
2017-03-17 05:55:27 +02:00
2017-06-07 00:02:25 +03:00
template< class T, class I> using tuple_element =
typename std::tuple_element< I::value, T> ::type;
2017-03-17 05:55:27 +02:00
2017-06-07 00:02:25 +03:00
template< class T> using from_tuple_like =
mp_product< tuple_element, mp_list< T> , mp_iota< std::tuple_size< T> > > ;
2017-03-17 05:55:27 +02:00
2017-06-07 00:02:25 +03:00
template< class... Tp,
class R = mp_append< std::tuple< > , from_tuple_like< remove_cv_ref< Tp> > ...> >
R tuple_cat( Tp & & ... tp )
{
std::size_t const N = sizeof...(Tp);
2017-03-17 05:55:27 +02:00
2017-06-07 00:02:25 +03:00
// inner
2017-03-17 05:55:27 +02:00
2017-06-07 00:02:25 +03:00
using list1 = mp_list< from_tuple_like< remove_cv_ref< Tp> > ...> ;
using list2 = mp_iota_c< N> ;
2017-03-17 05:55:27 +02:00
2017-06-07 00:02:25 +03:00
using list3 = mp_transform< mp_fill, list1, list2> ;
2017-03-17 05:55:27 +02:00
2017-06-07 00:02:25 +03:00
using inner = mp_apply< mp_append, list3> ;
2017-03-17 05:55:27 +02:00
2017-06-07 00:02:25 +03:00
// outer
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
using list4 = mp_transform< F, list1> ;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
using outer = mp_apply< mp_append, list4> ;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
//
2017-05-17 20:47:25 +03:00
2017-06-10 03:44:31 +03:00
return tuple_cat_< R> ( inner(), outer(),
std::forward_as_tuple( std::forward< Tp> (tp)... ) );
2017-06-07 00:02:25 +03:00
}< / code > < / pre >
< / div >
< / div >
< / div >
< div class = "sect2" >
< h3 id = "computing_return_types" > Computing Return Types< / h3 >
< div class = "paragraph" >
< p > C++17 has a standard variant type, called < code > std::variant< / code > . It also defines a function template
< code > std::visit< / code > that can be used to apply a function to the contained value of one or more variants.
So for instance, if the variant < code > v1< / code > contains < code > 1< / code > , and the variant < code > v2< / code > contains < code > 2.0f< / code > ,
< code > std::visit(f, v1, v2)< / code > will call < code > f(1, 2.0f)< / code > .< / p >
< / div >
< div class = "paragraph" >
< p > However, < code > std::visit< / code > has one limitation: it cannot return a result unless all
possible applications of the function have the same return type. If, for instance, < code > v1< / code > and < code > v2< / code >
are both of type < code > std::variant< short, int, float> < / code > ,< / p >
< / div >
< div class = "literalblock" >
< div class = "content" >
< pre > std::visit( []( auto const& x, auto const& y ){ return x + y; }, v1, v2 );< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > will fail to compile because the result of < code > x + y< / code > can be either < code > int< / code > or < code > float< / code > depending on
what < code > v1< / code > and < code > v2< / code > hold.< / p >
< / div >
< div class = "paragraph" >
< p > A type that can hold either < code > int< / code > or < code > float< / code > already exists, called, surprisingly enough, < code > std::variant< int, float> < / code > .
Let’ s write our own function template < code > rvisit< / code > that is the same as < code > visit< / code > but returns a < code > variant< / code > :< / p >
< / div >
< div class = "listingblock" >
< div class = "content" >
< pre class = "highlight" > < code > template< class F, class... V> auto rvisit( F& & f, V& & ... v )
{
using R = /*...*/;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
return std::visit( [& ]( auto& & ... x )
{ return R( std::forward< F> (f)( std::forward< decltype(x)> (x)... ) ); },
std::forward< V> ( v )... );
}< / code > < / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > What this does is basically calls < code > std::visit< / code > to do the work, but instead of passing it < code > f< / code > , we pass a lambda that does the same as < code > f< / code > except
it converts the result to a common type < code > R< / code > . < code > R< / code > is supposed to be < code > std::variant< … ​ > < / code > where the ellipsis denotes the return types of
calling < code > f< / code > with all possible combinations of variant values.< / p >
< / div >
< div class = "paragraph" >
< p > We’ ll first define a helper quoted metafunction < code > Qret< F> < / code > that returns the result of the application of < code > F< / code > to arguments of type < code > T… ​ < / code > :< / p >
< / div >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class F> struct Qret
{
2017-06-10 03:44:31 +03:00
template< class... T> using fn =
decltype( std::declval< F> ()( std::declval< T> ()... ) );
2017-06-07 00:02:25 +03:00
};< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > (Unfortunately, we can’ t just define this metafunction inside < code > rvisit< / code > ; the language prohibits defining template aliases inside functions.)< / p >
< / div >
< div class = "paragraph" >
< p > With < code > Qret< / code > in hand, a < code > variant< / code > of the possible return types is just a matter of applying it over the possible combinations of the variant values:< / p >
< / div >
< div class = "literalblock" >
< div class = "content" >
< pre > using R = mp_product_q< Qret< F> , std::remove_reference_t< V> ...> ;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Why does this work? < code > mp_product< F, L1< T1… ​ > , L2< T2… ​ > , … ​ , Ln< Tn… ​ > > < / code > returns < code > L1< F< U1, U2, … ​ , Un> , … ​ > < / code > , where < code > Ui< / code > traverse all
possible combinations of list values. Since in our case all < code > Li< / code > are < code > std::variant< / code > , the result will also be < code > std::variant< / code > . (< code > mp_product_q< / code > is
the same as < code > mp_product< / code > , but for quoted metafunctions such as our < code > Qret< F> < / code > .)< / p >
< / div >
< div class = "paragraph" >
< p > One more step remains. Suppose that, as above, we’ re passing two variants of type < code > std::variant< short, int, float> < / code > and < code > F< / code > is
< code > []( auto const& x, auto const& y ){ return x + y; }< / code > . This will generate < code > R< / code > of length 9, one per each combination, but many of those
2017-06-10 03:44:31 +03:00
elements will be the same, either < code > int< / code > or < code > float< / code > , and we need to filter out the duplicates. So, we pass the result to < code > mp_unique< / code > :< / p >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "literalblock" >
< div class = "content" >
< pre > using R = mp_unique< mp_product_q< Qret< F> , std::remove_reference_t< V> ...> > ;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > and we’ re done:< / p >
< / div >
< div class = "listingblock" >
< div class = "content" >
< pre class = "highlight" > < code > #include < boost/mp11.hpp>
#include < boost/core/demangle.hpp>
#include < variant>
#include < type_traits>
#include < typeinfo>
#include < iostream>
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
using namespace boost::mp11;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
template< class F> struct Qret
{
2017-06-10 03:44:31 +03:00
template< class... T> using fn =
decltype( std::declval< F> ()( std::declval< T> ()... ) );
2017-06-07 00:02:25 +03:00
};
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
template< class F, class... V> auto rvisit( F& & f, V& & ... v )
{
using R = mp_unique< mp_product_q< Qret< F> , std::remove_reference_t< V> ...> > ;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
return std::visit( [& ]( auto& & ... x )
{ return R( std::forward< F> (f)( std::forward< decltype(x)> (x)... ) ); },
std::forward< V> ( v )... );
}
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
template< class T> std::string name()
{
return boost::core::demangle( typeid(T).name() );
}
2017-05-17 20:47:25 +03:00
2017-06-10 03:44:31 +03:00
template< class V> void print_variant( char const * n, V const& v )
2017-06-07 00:02:25 +03:00
{
2017-06-10 03:44:31 +03:00
std::cout < < "(" < < name< decltype(v)> () < < ")" < < n < < ": ";
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
std::visit( []( auto const& x )
2017-06-10 03:44:31 +03:00
{ std::cout < < "(" < < name< decltype(x)> () < < ")" < < x < < std::endl; }, v );
}
int main()
{
std::variant< char, int, float> v1( 1 );
2017-05-17 20:47:25 +03:00
2017-06-10 03:44:31 +03:00
print_variant( "v1", v1 );
2017-05-17 20:47:25 +03:00
2017-06-10 03:44:31 +03:00
std::variant< short, int, double> v2( 3.14 );
print_variant( "v2", v2 );
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
auto v3 = rvisit( []( auto const& x, auto const& y ){ return x + y; }, v1, v2 );
2017-05-17 20:47:25 +03:00
2017-06-10 03:44:31 +03:00
print_variant( "v3", v3 );
2017-06-07 00:02:25 +03:00
}< / code > < / pre >
< / div >
< / div >
< / div >
< / div >
< / div >
< div class = "sect1" >
< h2 id = "reference" > Reference< / h2 >
< div class = "sectionbody" >
< div class = "paragraph" >
< p > The contents of the library are in namespace < code > boost::mp11< / code > .< / p >
< / div >
< div class = "sect2" >
< h3 id = "integral" > Integral Constants, < boost/mp11/integral.hpp> < / h3 >
< div class = "paragraph" >
< p > For an Mp11 integral constant type < code > T< / code > , < code > T::value< / code > is an integral constant in the C++ sense.< / p >
< / div >
< div class = "sect3" >
< h4 id = "mp_bool_b" > mp_bool< B> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< bool B> using mp_bool = std::integral_constant< bool, B> ;< / pre >
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "paragraph" >
< p > Same as < code > std::bool_constant< / code > in C++17.< / p >
< / div >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_true" > mp_true< / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > using mp_true = mp_bool< true> ;< / pre >
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "paragraph" >
< p > Same as < code > std::true_type< / code > .< / p >
< / div >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_false" > mp_false< / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > using mp_false = mp_bool< false> ;< / pre >
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "paragraph" >
< p > Same as < code > std::false_type< / code > .< / p >
< / div >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_to_bool_t" > mp_to_bool< T> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class T> using mp_to_bool = mp_bool< static_cast< bool> (T::value)> ;< / pre >
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_not_t" > mp_not< T> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class T> using mp_not = mp_bool< !T::value > ;< / pre >
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_int_i" > mp_int< I> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< int I> using mp_int = std::integral_constant< int, I> ;< / pre >
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_size_t_n" > mp_size_t< N> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< std::size_t N> using mp_size_t = std::integral_constant< std::size_t, N> ;< / pre >
< / div >
< / div >
< / div >
< / div >
< div class = "sect2" >
< h3 id = "list" > List Operations, < boost/mp11/list.hpp> < / h3 >
< div class = "sect3" >
< h4 id = "mp_list_t" > mp_list< T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class... T> struct mp_list {};< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_list< / code > is the standard list type of Mp11, although the library is not restricted to it and can operate on arbitrary class templates
such as < code > std::tuple< / code > or < code > std::variant< / code > . Even < code > std::pair< / code > can be used if the transformation does not alter the number of the elements in
the list.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_size_l" > mp_size< L> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L> using mp_size = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_size< L> < / code > returns the number of elements in the list < code > L< / code > , as a < code > mp_size_t< / code > . In other words, < code > mp_size< L< T… ​ > > < / code > is an alias for
< code > mp_size_t< sizeof… ​ (T)> < / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 1. Using mp_size with mp_list< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L1 = mp_list< > ;
using R1 = mp_size< L1> ; // mp_size_t< 0> < / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 2. Using mp_size with std::pair< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L2 = std::pair< int, int> ;
using R2 = mp_size< L2> ; // mp_size_t< 2> < / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 3. Using mp_size with std::tuple< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L3 = std::tuple< float> ;
using R3 = mp_size< L3> ; // mp_size_t< 1> < / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_empty_l" > mp_empty< L> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L> using mp_empty = mp_bool< mp_size< L> ::value == 0> ;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_empty< L> < / code > is an alias for < code > mp_true< / code > if the list < code > L< / code > is empty, for < code > mp_false< / code > otherwise.< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 4. Using mp_empty with std::tuple< / div >
< div class = "content" >
< pre class = "highlight" > < code > using L1 = std::tuple< float> ;
using R1 = mp_empty< L1> ; // mp_false
using L2 = std::tuple< > ;
using R2 = mp_empty< L2> ; // mp_true< / code > < / pre >
< / div >
< / div >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_front_l" > mp_front< L> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L> using mp_front = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_front< L> < / code > is the first element of the list < code > L< / code > . That is, < code > mp_front< L< T1, T… ​ > > < / code > is an alias for < code > T1< / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 5. Using mp_front with std::pair< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L1 = std::pair< int, float> ;
using R1 = mp_front< L1> ; // int< / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 6. Using mp_front with std::tuple< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L2 = std::tuple< float, double, long double> ;
using R2 = mp_front< L2> ; // float< / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 7. Using mp_front with mp_list< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L3 = mp_list< char[1], char[2], char[3], char[4]> ;
using R3 = mp_front< L3> ; // char[1]< / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_pop_front_l" > mp_pop_front< L> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L> using mp_pop_front = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_pop_front< L> < / code > removes the first element of the list < code > L< / code > . That is, < code > mp_pop_front< L< T1, T… ​ > > < / code > is an alias for < code > L< T… ​ > < / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 8. Using mp_pop_front with std::tuple< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L1 = std::tuple< float, double, long double> ;
using R1 = mp_pop_front< L1> ; // std::tuple< double, long double> < / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 9. Using mp_pop_front with mp_list< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L2 = mp_list< void> ;
using R2 = mp_pop_front< L2> ; // mp_list< > < / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_first_l" > mp_first< L> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L> using mp_first = mp_front< L> ;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_first< / code > is another name for < code > mp_front< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_rest_l" > mp_rest< L> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L> using mp_rest = mp_pop_front< L> ;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_rest< / code > is another name for < code > mp_pop_front< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_second_l" > mp_second< L> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L> using mp_second = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_second< L> < / code > is the second element of the list < code > L< / code > . That is, < code > mp_second< L< T1, T2, T… ​ > > < / code > is an alias for < code > T2< / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 10. Using mp_second with std::pair< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L1 = std::pair< int, float> ;
using R1 = mp_second< L1> ; // float< / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 11. Using mp_second with std::tuple< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L2 = std::tuple< float, double, long double> ;
using R2 = mp_second< L2> ; // double< / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 12. Using mp_second with mp_list< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L3 = mp_list< char[1], char[2], char[3], char[4]> ;
using R3 = mp_second< L3> ; // char[2]< / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_third_l" > mp_third< L> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L> using mp_third = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_third< L> < / code > is the third element of the list < code > L< / code > . That is, < code > mp_third< L< T1, T2, T3, T… ​ > > < / code > is an alias for < code > T3< / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 13. Using mp_third with std::tuple< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L1 = std::tuple< float, double, long double> ;
using R1 = mp_third< L1> ; // long double< / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 14. Using mp_third with mp_list< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L2 = mp_list< char[1], char[2], char[3], char[4]> ;
using R2 = mp_third< L2> ; // char[3]< / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_push_front_l_t" > mp_push_front< L, T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, class... T> using mp_push_front = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_push_front< L, T… ​ > < / code > inserts the elements < code > T… ​ < / code > at the front of the list < code > L< / code > . That is, < code > mp_push_front< L< U… ​ > , T… ​ > < / code >
is an alias for < code > L< T… ​ , U… ​ > < / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 15. Using mp_push_front with std::tuple< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L1 = std::tuple< double, long double> ;
using R1 = mp_push_front< L1, float> ; // std::tuple< float, double, long double> < / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 16. Using mp_push_front with mp_list< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L2 = mp_list< void> ;
using R2 = mp_push_front< L2, char[1], char[2]> ; // mp_list< char[1], char[2], void> < / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_push_back_l_t" > mp_push_back< L, T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, class... T> using mp_push_back = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_push_back< L, T… ​ > < / code > inserts the elements < code > T… ​ < / code > at the back of the list < code > L< / code > . That is, < code > mp_push_back< L< U… ​ > , T… ​ > < / code >
is an alias for < code > L< U… ​ , T… ​ > < / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 17. Using mp_push_back with std::tuple< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L1 = std::tuple< double, long double> ;
using R1 = mp_push_back< L1, float> ; // std::tuple< double, long double, float> < / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 18. Using mp_push_back with mp_list< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L2 = mp_list< void> ;
using R2 = mp_push_back< L2, char[1], char[2]> ; // mp_list< void, char[1], char[2]> < / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_rename_l_y" > mp_rename< L, Y> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, template< class...> class Y> using mp_rename = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_rename< L, Y> < / code > changes the type of the list < code > L< / code > to < code > Y< / code > . That is, < code > mp_rename< L< T… ​ > , Y> < / code > is an alias for < code > Y< T… ​ > < / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 19. Using mp_rename to rename std::pair to std::tuple< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L1 = std::pair< double, long double> ;
using R1 = mp_rename< L1, std::tuple> ; // std::tuple< double, long double> < / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 20. Using mp_rename to rename std::tuple to mp_list< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L2 = std::tuple< void> ;
using R2 = mp_rename< L2, mp_list> ; // mp_list< void> < / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_apply_f_l" > mp_apply< F, L> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< template< class...> class F, class L> using mp_apply = mp_rename< L, F> ;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_apply< F, L> < / code > applies the metafunction < code > F< / code > to the contents of the list < code > L< / code > , that is, < code > mp_apply< F, L< T… ​ > > < / code > is an alias for < code > F< T… ​ > < / code > .
(< code > mp_apply< / code > is the same as < code > mp_rename< / code > with the arguments reversed.)< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 21. Using mp_apply with std::pair< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L1 = std::pair< double, long double> ;
using R1 = mp_apply< std::is_same, L1> ; // std::is_same< double, long double> < / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_apply_q_q_l" > mp_apply_q< Q, L> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class Q, class L> using mp_apply_q = mp_apply< Q::template fn, L> ;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Same as < code > mp_apply< / code > , but takes a quoted metafunction.< / p >
< / div >
< div class = "listingblock" >
2017-06-10 03:44:31 +03:00
< div class = "title" > Code Example 22. Using mp_apply_q with mp_bind_front< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
< pre class = "highlight" > < code > using L1 = std::tuple< double, long double> ;
using L2 = mp_list< int, long> ;
2017-05-17 20:47:25 +03:00
2017-06-07 00:02:25 +03:00
using R1 = mp_apply_q< mp_bind_front< mp_push_back, L1> , L2> ;
2017-06-10 03:44:31 +03:00
// R1 is std::tuple< double, long double, int, long> < / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_append_l" > mp_append< L… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class... L> using mp_append = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_append< L… ​ > < / code > concatenates the lists in < code > L… ​ < / code > into a single list that has the same type as the first list. < code > mp_append< > < / code >
is an alias for < code > mp_list< > < / code > . < code > mp_append< L1< T1… ​ > , L2< T2… ​ > , … ​ , Ln< Tn… ​ > > < / code > is an alias for < code > L1< T1… ​ , T2… ​ , … ​ , Tn… ​ > < / code > .< / p >
< / div >
< div class = "listingblock" >
2017-06-10 03:44:31 +03:00
< div class = "title" > Code Example 23. Using mp_append with lists of various types< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
< pre class = "highlight" > < code > using L1 = std::tuple< double, long double> ;
using L2 = mp_list< int> ;
using L3 = std::pair< short, long> ;
using L4 = mp_list< > ;
2017-05-18 14:59:46 +03:00
2017-06-10 03:44:31 +03:00
using R1 = mp_append< L1, L2, L3, L4> ;
// std::tuple< double, long double, int, short, long> < / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_replace_front_l_t" > mp_replace_front< L, T> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, class T> using mp_replace_front = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_replace_front< L, T> < / code > replaces the first element of the list < code > L< / code > with < code > T< / code > . That is, < code > mp_replace_front< L< U1, U… ​ > , T> < / code > is
an alias for < code > L< T, U… ​ > < / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 24. Using mp_replace_front with std::pair< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L1 = std::pair< int, float> ;
using R1 = mp_replace_front< L1, void> ; // std::pair< void, float> < / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 25. Using mp_replace_front with std::tuple< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L2 = std::tuple< float, double, long double> ;
using R2 = mp_replace_front< L2, void> ; // std::tuple< void, double, long double> < / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 26. Using mp_replace_front with mp_list< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L3 = mp_list< char[1], char[2], char[3], char[4]> ;
using R3 = mp_replace_front< L3, void> ; // mp_list< void, char[2], char[3], char[4]> ;< / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_replace_first_l_t" > mp_replace_first< L, T> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, class T> using mp_replace_first = mp_replace_front< L, T> ;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_replace_first< / code > is another name for < code > mp_replace_front< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_replace_second_l_t" > mp_replace_second< L, T> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, class T> using mp_replace_second = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_replace_second< L, T> < / code > replaces the second element of the list < code > L< / code > with < code > T< / code > . That is, < code > mp_replace_second< L< U1, U2, U… ​ > , T> < / code >
is an alias for < code > L< U1, T, U… ​ > < / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 27. Using mp_replace_second with std::pair< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L1 = std::pair< int, float> ;
using R1 = mp_replace_second< L1, void> ; // std::pair< int, void> < / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 28. Using mp_replace_second with std::tuple< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L2 = std::tuple< float, double, long double> ;
using R2 = mp_replace_second< L2, void> ; // std::tuple< float, void, long double> < / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 29. Using mp_replace_front with mp_list< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L3 = mp_list< char[1], char[2], char[3], char[4]> ;
using R3 = mp_replace_second< L3, void> ; // mp_list< char[1], void, char[3], char[4]> ;< / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_replace_third_l_t" > mp_replace_third< L, T> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, class T> using mp_replace_third = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_replace_third< L, T> < / code > replaces the third element of the list < code > L< / code > with < code > T< / code > . That is, < code > mp_replace_third< L< U1, U2, U3, U… ​ > , T> < / code >
is an alias for < code > L< U1, U2, T, U… ​ > < / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 30. Using mp_replace_third with std::tuple< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L1 = std::tuple< float, double, long double> ;
using R1 = mp_replace_third< L1, void> ; // std::tuple< float, double, void> < / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 31. Using mp_replace_third with mp_list< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using L2 = mp_list< char[1], char[2], char[3], char[4]> ;
using R2 = mp_replace_third< L2, void> ; // mp_list< char[1], char[2], void, char[4]> ;< / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< / div >
< div class = "sect2" >
< h3 id = "utility" > Utility Components, < boost/mp11/utility.hpp> < / h3 >
< div class = "sect3" >
< h4 id = "mp_identity_t" > mp_identity< T> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class T> struct mp_identity
{
using type = T;
};< / pre >
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "paragraph" >
< p > < code > mp_identity< / code > is a simple < em > transformation type trait< / em > (as per the C++ standard)
that just returns the same type. It’ s useful both as such, and as a type wrapper
useful for passing types as values to functions.< / p >
< / div >
< div class = "listingblock" >
< div class = "title" > Code Example 32. Using mp_identity as a type trait< / div >
< div class = "content" >
< pre class = "highlight" > < code > template< class T> using addp_if_not_ref =
typename mp_if< std::is_reference< T> , mp_identity< T> , std::add_pointer< T> > ::type;< / code > < / pre >
< / div >
< / div >
< div class = "listingblock" >
< div class = "title" > Code Example 33. Using mp_identity to protect qualifiers and references< / div >
< div class = "content" >
< pre class = "highlight" > < code > template< class T> void print1()
{
std::cout < < typeid(T).name() < < std::endl;
}
template< class T> void print2()
{
std::cout < < typeid(mp_identity< T> ).name() < < std::endl;
}
int main()
{
print1< int const& > (); // 'int'
print2< int const& > (); // 'mp_identity< int const & > '
}< / code > < / pre >
< / div >
< / div >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_identity_t_t" > mp_identity_t< T> < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-10 04:13:39 +03:00
< pre > template< class T> using mp_identity_t = typename mp_identity< T> ::type;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_inherit_t" > mp_inherit< T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class... T> struct mp_inherit: T... {};< / pre >
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_if_c_c_t_e" > mp_if_c< C, T, E… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< bool C, class T, class... E> using mp_if_c = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_if_c< true, T, E… ​ > < / code > is an alias for < code > T< / code > . < code > mp_if_c< false, T, E> < / code > is an alias for < code > E< / code > . Otherwise, the result is a substitution failure.< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 34. Using mp_if_c to select between two alternatives< / div >
2017-06-09 20:35:21 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using R1 = mp_if_c< true, int, void> ; // int
using R2 = mp_if_c< false, int, void> ; // void< / code > < / pre >
2017-06-09 20:35:21 +03:00
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 35. Using mp_if_c to fail substitution when a condition is not met< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > template< class I> using void_if_5 = mp_if_c< I::value == 5, void> ;< / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "paragraph" >
< p > This example returns < code > void< / code > when < code > I::value< / code > is 5, and generates a substitution failure
otherwise. It’ s the same as < code > std::enable_if_t< I::value == 5> < / code > in C++14, or
< code > typename std::enable_if< I::value == 5> ::type< / code > in C++11.< / p >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_if_c_t_e" > mp_if< C, T, E… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-09 20:35:21 +03:00
< pre > template< class C, class T, class E...> using mp_if =
mp_if_c< static_cast< bool> (C::value), T, E...> ;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > Like < code > mp_if_c< / code > , but the first argument is a type.< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 36. Using mp_if to select between two alternatives< / div >
< div class = "content" >
< pre class = "highlight" > < code > using R1 = mp_if< mp_true, int, void> ; // int
using R2 = mp_if< mp_false, int, void> ; // void< / code > < / pre >
< / div >
< / div >
< div class = "listingblock" >
< div class = "title" > Code Example 37. Using mp_if to fail substitution when a condition is not met< / div >
< div class = "content" >
< pre class = "highlight" > < code > template< class T> using void_if_const = mp_if< std::is_const< T> , void> ;
template< class... T> using void_if_all_const =
mp_if< mp_all< std::is_const< T> ...> , void> ;
template< class T> using if_non_const = mp_if< mp_not< std::is_const< T> > , T> ;< / code > < / pre >
< / div >
< / div >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_eval_if_c_c_t_f_u" > mp_eval_if_c< C, T, F, U… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre > template< bool C, class T, template< class...> class F, class... U> using mp_eval_if_c =
/*...*/;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_eval_if_c< C, T, F, U… ​ > < / code > is an alias for < code > T< / code > when < code > C< / code > is < code > true< / code > , for < code > F< U… ​ > < / code > otherwise. Its purpose
is to avoid evaluating < code > F< U… ​ > < / code > when the condition is < code > true< / code > as it may not be valid in this case.< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 38. Using mp_eval_if_c to select the first pack element, or void< / div >
< div class = "content" >
< pre class = "highlight" > < code > template< class... T> using first_or_void =
mp_eval_if_c< sizeof...(T) == 0, void, mp_apply, mp_first, mp_list< T...> > ;< / code > < / pre >
< / div >
< / div >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_eval_if_c_t_f_u" > mp_eval_if< C, T, F, U… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-09 20:35:21 +03:00
< pre > template< class C, class T, template< class...> class F, class... U> using mp_eval_if =
mp_eval_if_c< static_cast< bool> (C::value), T, F, U...> ;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > Like < code > mp_eval_if_c< / code > , but the first argument is a type.< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 39. Using mp_eval_if to select the first list element, or void< / div >
< div class = "content" >
< pre class = "highlight" > < code > template< class L> using first_or_void = mp_eval_if< mp_empty< L> , void, mp_first, L> ;< / code > < / pre >
< / div >
< / div >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_eval_if_q_c_t_q_u" > mp_eval_if_q< C, T, Q, U… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-09 20:35:21 +03:00
< pre > template< class C, class T, class Q, class... U> using mp_eval_if_q =
mp_eval_if< C, T, Q::template fn, U...> ;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > Like < code > mp_eval_if< / code > , but takes a quoted metafunction.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_valid_f_t" > mp_valid< F, T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< template< class...> class F, class... T> using mp_valid = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_valid< F, T… ​ > < / code > is an alias for < code > mp_true< / code > when < code > F< T… ​ > < / code > is a valid expression, for < code > mp_false< / code > otherwise.< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 40. Using mp_valid to write a metafunction that checks for the existence of a nested type< / div >
< div class = "content" >
< pre class = "highlight" > < code > template< class T> using get_nested_type = typename T::type;
template< class T> struct has_nested_type: mp_valid< get_nested_type, T> {};< / code > < / pre >
< / div >
< / div >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_defer_f_t" > mp_defer< F, T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< template< class...> class F, class... T> using mp_defer = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > When < code > mp_valid< F, T… ​ > < / code > is < code > mp_true< / code > , < code > mp_defer< F, T… ​ > < / code > is a struct with a nested type < code > type< / code > which is an alias for < code > F< T… ​ > < / code > . Otherwise,
< code > mp_defer< F, T… ​ > < / code > is an empty struct.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_quote_f" > mp_quote< F> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< template< class...> class F> struct mp_quote
{
template< class... T> using fn = F< T...> ;
};< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_quote< F> < / code > transforms the template < code > F< / code > into a type with a nested template < code > fn< / code > such that < code > fn< T… ​ > < / code > returns < code > F< T… ​ > < / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 41. Using mp_quote to make a list of metafunctions< / div >
< div class = "content" >
< pre class = "highlight" > < code > using LQ = mp_list< mp_quote< std::is_const> , mp_quote< std::is_volatile> > ;< / code > < / pre >
< / div >
< / div >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_invoke_q_t" > mp_invoke< Q, T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class Q, class... T> using mp_invoke = typename Q::template fn< T...> ;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_invoke< Q, T… ​ > < / code > evaluates the nested template < code > fn< / code > of a quoted metafunction. < code > mp_invoke< mp_quote< F> , T… ​ > < / code > returns < code > F< T… ​ > < / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 42. Using mp_invoke to invoke a list of metafunctions, technique 1< / div >
< div class = "content" >
< pre class = "highlight" > < code > using LQ = mp_list< mp_quote< std::is_const> , mp_quote< std::is_volatile> > ;
template< class T> using is_const_and_volatile =
mp_all< mp_product< mp_invoke, LQ, mp_list< T> > > ;< / code > < / pre >
< / div >
< / div >
< div class = "listingblock" >
< div class = "title" > Code Example 43. Using mp_invoke to invoke a list of metafunctions, technique 2< / div >
< div class = "content" >
< pre class = "highlight" > < code > template< class T> using is_const_and_volatile =
mp_all< mp_transform_q< mp_bind_back< mp_invoke, T> , LQ> > ;< / code > < / pre >
< / div >
< / div >
< div class = "listingblock" >
< div class = "title" > Code Example 44. Using mp_invoke to invoke a list of metafunctions, technique 3< / div >
< div class = "content" >
< pre class = "highlight" > < code > template< class T> using is_const_and_volatile =
mp_all< mp_transform< mp_invoke, LQ, mp_fill< LQ, T> > > ;< / code > < / pre >
< / div >
< / div >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "sect2" >
< h3 id = "algorithm" > Algorithms, < boost/mp11/algorithm.hpp> < / h3 >
< div class = "sect3" >
< h4 id = "mp_assign_l1_l2" > mp_assign< L1, L2> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L1, class L2> using mp_assign = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_assign< L1< T1… ​ > , L2< T2… ​ > > < / code > is an alias for < code > L1< T2… ​ > < / code > . That is, it replaces the elements of < code > L1< / code > with those of < code > L2< / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 45. Using mp_assign with mp_list and std::tuple< / div >
< div class = "content" >
< pre class = "highlight" > < code > using L1 = std::tuple< long> ;
using L2 = mp_list< int, float> ;
using R1 = mp_assign< L1, L2> ; // std::tuple< int, float> < / code > < / pre >
< / div >
< / div >
< div class = "listingblock" >
< div class = "title" > Code Example 46. Using mp_assign with mp_list and std::pair< / div >
< div class = "content" >
< pre class = "highlight" > < code > using L1 = std::pair< long, char> ;
using L2 = mp_list< int, float> ;
using R1 = mp_assign< L1, L2> ; // std::pair< int, float> < / code > < / pre >
< / div >
< / div >
2017-06-11 04:35:34 +03:00
< table class = "tableblock frame-all grid-all" style = "width: 85%;" >
< caption class = "title" > Illustration 1. mp_assign< / caption >
< colgroup >
< col style = "width: 50%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< / colgroup >
< tbody >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > L1< / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 2< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > n< / sub > < / code > < / p > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > L2< / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > 2< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > n< / sub > < / code > < / p > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > mp_assign< L1, L2> < / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > 2< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > n< / sub > < / code > < / p > < / td >
< / tr >
< / tbody >
< / table >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_clear_l" > mp_clear< L> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L> using mp_clear = mp_assign< L, mp_list< > > ;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_clear< L< T… ​ > > < / code > is an alias for < code > L< > < / code > , that is, it removes the elements of < code > L< / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 47. Using mp_clear with std::tuple< / div >
< div class = "content" >
< pre class = "highlight" > < code > using L1 = std::tuple< int, float> ;
using R1 = mp_clear< L1> ; // std::tuple< > < / code > < / pre >
< / div >
< / div >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_transform_f_l" > mp_transform< F, L… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< template< class...> class F, class... L> using mp_transform = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_transform< F, L1< T1… ​ > , L2< T2… ​ > , … ​ , Ln< Tn… ​ > > < / code > applies < code > F< / code > to each successive tuple of elements and returns < code > L1< F< T1, T2, … ​ , Tn> … ​ > < / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 48. Using mp_transform to produce a list of pointers from a list of pointees< / div >
< div class = "content" >
< pre class = "highlight" > < code > template< class T> using add_pointer_t =
typename std::add_pointer< T> ::type; // std::add_pointer_t in C++14
using L1 = std::tuple< void, int, float> ;
using R1 = mp_transform< add_pointer_t, L1> ; // std::tuple< void*, int*, float*> < / code > < / pre >
< / div >
< / div >
< div class = "listingblock" >
< div class = "title" > Code Example 49. Using mp_transform to compare the contents of two lists of types< / div >
< div class = "content" >
< pre class = "highlight" > < code > using L1 = std::tuple< void, int, float> ;
using L2 = mp_list< void, int, float> ;
using R1 = mp_all< mp_transform< std::is_same, L1, L2> > ; // mp_true< / code > < / pre >
< / div >
< / div >
< div class = "listingblock" >
< div class = "title" > Code Example 50. Using mp_transform to compare the contents of two lists of integral constants< / div >
< div class = "content" >
< pre class = "highlight" > < code > template< class T1, class T2> using eq = mp_bool< T1::value == T2::value> ;
using L1 = std::tuple< mp_int< 1> , mp_int< 2> , mp_int< 3> > ;
using L2 = mp_list< mp_size_t< 1> , mp_size_t< 2> , mp_size_t< 3> > ;
using R1 = mp_all< mp_transform< eq, L1, L2> > ; // mp_true< / code > < / pre >
< / div >
< / div >
< table class = "tableblock frame-all grid-all" style = "width: 85%;" >
2017-06-11 04:35:34 +03:00
< caption class = "title" > Illustration 2. mp_transform on one list< / caption >
2017-06-10 03:44:31 +03:00
< colgroup >
< col style = "width: 50%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< / colgroup >
< tbody >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > L1< / strong > < / code > < / p > < / td >
2017-06-11 04:35:34 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 2< / sub > < / code > < / p > < / td >
2017-06-10 03:44:31 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
2017-06-11 04:35:34 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > n< / sub > < / code > < / p > < / td >
2017-06-10 03:44:31 +03:00
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > mp_transform< F, L1> < / strong > < / code > < / p > < / td >
2017-06-11 04:35:34 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > F< A< sub > 1< / sub > > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > F< A< sub > 2< / sub > > < / code > < / p > < / td >
2017-06-10 03:44:31 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
2017-06-11 04:35:34 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > F< A< sub > n< / sub > > < / code > < / p > < / td >
2017-06-10 03:44:31 +03:00
< / tr >
< / tbody >
< / table >
< table class = "tableblock frame-all grid-all" style = "width: 85%;" >
2017-06-11 04:35:34 +03:00
< caption class = "title" > Illustration 3. mp_transform on two lists< / caption >
2017-06-10 03:44:31 +03:00
< colgroup >
< col style = "width: 50%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< / colgroup >
< tbody >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > L1< / strong > < / code > < / p > < / td >
2017-06-11 04:35:34 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 2< / sub > < / code > < / p > < / td >
2017-06-10 03:44:31 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
2017-06-11 04:35:34 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > n< / sub > < / code > < / p > < / td >
2017-06-10 03:44:31 +03:00
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > L2< / strong > < / code > < / p > < / td >
2017-06-11 04:35:34 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > 2< / sub > < / code > < / p > < / td >
2017-06-10 03:44:31 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
2017-06-11 04:35:34 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > n< / sub > < / code > < / p > < / td >
2017-06-10 03:44:31 +03:00
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > mp_transform< F, L1, L2> < / strong > < / code > < / p > < / td >
2017-06-11 04:35:34 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > F< A< sub > 1< / sub > ,B< sub > 1< / sub > > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > F< A< sub > 2< / sub > ,B< sub > 2< / sub > > < / code > < / p > < / td >
2017-06-10 03:44:31 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
2017-06-11 04:35:34 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > F< A< sub > n< / sub > ,B< sub > n< / sub > > < / code > < / p > < / td >
2017-06-10 03:44:31 +03:00
< / tr >
< / tbody >
< / table >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_transform_q_q_l" > mp_transform_q< Q, L… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre > template< class Q, class... L> using mp_transform_q =
mp_transform< Q::template fn, L...> ;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > As < code > mp_transform< / code > , but takes a quoted metafunction.< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 51. Using mp_transform_q to count the occurences of < code > void< / code > in a list< / div >
< div class = "content" >
< pre class = "highlight" > < code > using L1 = std::tuple< void, int, float, void, int> ;
using R1 = mp_apply< mp_plus,
mp_transform_q< mp_bind_front< std::is_same, void> , L1> > ; // mp_int< 2> < / code > < / pre >
< / div >
< / div >
2017-06-11 04:35:34 +03:00
< table class = "tableblock frame-all grid-all" style = "width: 85%;" >
< caption class = "title" > Illustration 4. mp_transform_q on two lists< / caption >
< colgroup >
< col style = "width: 50%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< / colgroup >
< tbody >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > L1< / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 2< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > n< / sub > < / code > < / p > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > L2< / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > 2< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > n< / sub > < / code > < / p > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > mp_transform_q< Q, L1, L2> < / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > Q::fn< A< sub > 1< / sub > ,B< sub > 1< / sub > > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > Q::fn< A< sub > 2< / sub > ,B< sub > 2< / sub > > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > Q::fn< A< sub > n< / sub > ,B< sub > n< / sub > > < / code > < / p > < / td >
< / tr >
< / tbody >
< / table >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_transform_if_p_f_l" > mp_transform_if< P, F, L… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre > template< template< class...> class P, template< class...> class F, class L...>
using mp_transform_if = /*...*/;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_transform_if< P, F, L1, L2, … ​ , Ln> < / code > replaces the elements of the list < code > L1< / code > for which < code > mp_to_bool< P< T1, T2, … ​ , Tn> > < / code > is < code > mp_true< / code > with
< code > F< T1, T2, … ​ , Tn> < / code > , and returns the result, where < code > Ti< / code > are the corresponding elements of < code > Li< / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 52. Using mp_transform_if to replace the occurences of 'void' in a list with the corresponding elements of a second list< / div >
< div class = "content" >
< pre class = "highlight" > < code > using L1 = std::tuple< void, int, float, void, int> ;
using L2 = std::tuple< char[1], char[2], char[3], char[4], char[5]> ;
template< class T1, class T2> using first_is_void = std::is_same< T1, void> ;
template< class T1, class T2> using second = T2;
using R1 = mp_transform_if< first_is_void, second, L1, L2> ;
// std::tuple< char[1], int, float, char[4], int> < / code > < / pre >
< / div >
< / div >
2017-06-11 04:35:34 +03:00
< table class = "tableblock frame-all grid-all" style = "width: 85%;" >
< caption class = "title" > Illustration 5. mp_transform_if< / caption >
< colgroup >
< col style = "width: 50%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< / colgroup >
< tbody >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > L1< / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 2< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > n< / sub > < / code > < / p > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > P< A< sub > i< / sub > > < / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > mp_false< / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > mp_true< / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > mp_false< / code > < / p > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > L2< / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > 2< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > n< / sub > < / code > < / p > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > mp_transform_if< P, F, L1, L2> < / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > F< A< sub > 2< / sub > ,B< sub > 2< / sub > > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > n< / sub > < / code > < / p > < / td >
< / tr >
< / tbody >
< / table >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_transform_if_q_qp_qf_l" > mp_transform_if_q< Qp, Qf, L… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre > template< class Qp, class Qf, class... L> using mp_transform_if_q =
mp_transform_if< Qp::template fn, Qf::template fn, L...> ;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
2017-06-10 03:44:31 +03:00
< p > As < code > mp_transform_if< / code > , but takes quoted metafunctions.< / p >
< / div >
< div class = "listingblock" >
< div class = "title" > Code Example 53. Using mp_transform_if_q to replace the occurences of 'void' in a list with the corresponding elements of a second list< / div >
< div class = "content" >
< pre class = "highlight" > < code > using L1 = std::tuple< void, int, float, void, int> ;
using L2 = std::tuple< char[1], char[2], char[3], char[4], char[5]> ;
using R1 = mp_transform_if_q< mp_bind< std::is_same, _1, void> , _2, L1, L2> ;
// std::tuple< char[1], int, float, char[4], int> < / code > < / pre >
< / div >
2017-06-07 00:02:25 +03:00
< / div >
2017-06-11 04:35:34 +03:00
< table class = "tableblock frame-all grid-all" style = "width: 85%;" >
< caption class = "title" > Illustration 6. mp_transform_if_q< / caption >
< colgroup >
< col style = "width: 50%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< / colgroup >
< tbody >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > L1< / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 2< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > n< / sub > < / code > < / p > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > Qp::fn< A< sub > i< / sub > > < / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > mp_false< / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > mp_true< / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > mp_false< / code > < / p > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > L2< / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > 2< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > n< / sub > < / code > < / p > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > mp_transform_if_q< Qp, _2, L1, L2> < / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > 2< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > n< / sub > < / code > < / p > < / td >
< / tr >
< / tbody >
< / table >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_fill_l_v" > mp_fill< L, V> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, class V> using mp_fill = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_fill< L< T… ​ > , V> < / code > returns < code > L< V, V, … ​ , V> < / code > , with the result having the same size as the input.< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 54. Using mp_fill with std::tuple< / div >
< div class = "content" >
< pre class = "highlight" > < code > using L1 = std::tuple< void, int, float> ;
using R1 = mp_fill< L1, double> ; // std::tuple< double, double, double> < / code > < / pre >
< / div >
< / div >
< div class = "listingblock" >
< div class = "title" > Code Example 55. Using mp_fill with std::pair< / div >
< div class = "content" >
< pre class = "highlight" > < code > using L1 = std::pair< int, float> ;
using R1 = mp_fill< L1, void> ; // std::pair< void, void> < / code > < / pre >
< / div >
< / div >
2017-06-11 04:35:34 +03:00
< table class = "tableblock frame-all grid-all" style = "width: 85%;" >
< caption class = "title" > Illustration 7. mp_fill< / caption >
< colgroup >
< col style = "width: 50%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< / colgroup >
< tbody >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > L1< / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 2< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > n< / sub > < / code > < / p > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > mp_fill< L1, V> < / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > V< / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > V< / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > V< / code > < / p > < / td >
< / tr >
< / tbody >
< / table >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_count_l_v" > mp_count< L, V> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, class V> using mp_count = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_count< L, V> < / code > returns < code > mp_size_t< N> < / code > , where < code > N< / code > is the number of elements of < code > L< / code > same as < code > V< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_count_if_l_p" > mp_count_if< L, P> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, template< class...> class P> using mp_count_if = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_count_if< L, P> < / code > returns < code > mp_size_t< N> < / code > , where < code > N< / code > is the number of elements < code > T< / code > of < code > L< / code > for which < code > mp_to_bool< P< T> > < / code > is < code > mp_true< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_contains_l_v" > mp_contains< L, V> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, class V> using mp_contains = mp_to_bool< mp_count< L, V> > ;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_contains< L, V> < / code > is < code > mp_true< / code > when < code > L< / code > contains an element < code > V< / code > , < code > mp_false< / code > otherwise.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_repeat_c_l_n" > mp_repeat_c< L, N> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, std::size_t N> using mp_repeat_c = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_repeat_c< L, N> < / code > returns a list of the same type as < code > L< / code > that consists of < code > N< / code > concatenated copies of < code > L< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_repeat_l_n" > mp_repeat< L, N> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, class N> using mp_repeat = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Same as < code > mp_repeat_c< / code > but with a type argument < code > N< / code > . The number of copies is < code > N::value< / code > and must be nonnegative.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_product_f_l" > mp_product< F, L… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< template< class...> class F, class... L> using mp_product = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_product< F, L1< T1… ​ > , L2< T2… ​ > , … ​ , Ln< Tn… ​ > > < / code > evaluates < code > F< U1, U2, … ​ , Un> < / code > for values < code > Ui< / code > taken from
the Cartesian product of the lists, as if the elements < code > Ui< / code > are formed by < code > n< / code > nested loops, each traversing < code > Li< / code > .
It returns a list of type < code > L1< / code > containing the results of the application of < code > F< / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< table class = "tableblock frame-all grid-all" style = "width: 85%;" >
2017-06-11 04:35:34 +03:00
< caption class = "title" > Illustration 8. mp_product on two lists< / caption >
2017-06-10 03:44:31 +03:00
< colgroup >
< col style = "width: 50%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< / colgroup >
< tbody >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > L1< / strong > < / code > < / p > < / td >
2017-06-11 04:35:34 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 2< / sub > < / code > < / p > < / td >
2017-06-10 03:44:31 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
2017-06-11 04:35:34 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > n< / sub > < / code > < / p > < / td >
2017-06-10 03:44:31 +03:00
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > L2< / strong > < / code > < / p > < / td >
2017-06-11 04:35:34 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > 2< / sub > < / code > < / p > < / td >
2017-06-10 03:44:31 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
2017-06-11 04:35:34 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > B< sub > m< / sub > < / code > < / p > < / td >
2017-06-10 03:44:31 +03:00
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > mp_product< F, L1, L2> < / strong > < / code > < / p > < / td >
2017-06-11 04:35:34 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > F< A< sub > 1< / sub > ,B< sub > 1< / sub > > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > F< A< sub > 1< / sub > ,B< sub > 2< / sub > > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > F< A< sub > 1< / sub > ,B< sub > m< / sub > > < / code > < / p > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > F< A< sub > 2< / sub > ,B< sub > 1< / sub > > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > F< A< sub > 2< / sub > ,B< sub > 2< / sub > > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > F< A< sub > 2< / sub > ,B< sub > m< / sub > > < / code > < / p > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < / td >
< td class = "tableblock halign-center valign-middle" colspan = "4" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > F< A< sub > n< / sub > ,B< sub > 1< / sub > > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > F< A< sub > n< / sub > ,B< sub > 2< / sub > > < / code > < / p > < / td >
2017-06-10 03:44:31 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
2017-06-11 04:35:34 +03:00
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > F< A< sub > n< / sub > ,B< sub > m< / sub > > < / code > < / p > < / td >
2017-06-10 03:44:31 +03:00
< / tr >
< / tbody >
< / table >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_product_q_q_l" > mp_product_q< Q, L… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class Q, class... L> using mp_product_q = mp_product< Q::template fn, L...> ;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > As < code > mp_product< / code > , but takes a quoted metafunction.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_drop_c_l_n" > mp_drop_c< L, N> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, std::size_t N> using mp_drop_c = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_drop_c< L, N> < / code > removes the first < code > N< / code > elements of < code > L< / code > and returns the result.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_drop_l_n" > mp_drop< L, N> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, class N> using mp_drop = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Same as < code > mp_drop_c< / code > , but with a type argument < code > N< / code > . < code > N::value< / code > must be a nonnegative number.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_iota_c_n" > mp_iota_c< N> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< std::size_t N> using mp_iota_c = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_iota_c< N> < / code > is an alias for < code > mp_list< mp_size_t< 0> , mp_size_t< 1> , … ​ , mp_size_t< N-1> > < / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_iota_n" > mp_iota< N> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class N> using mp_iota = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Same as < code > mp_iota_c< / code > , but with a type argument < code > N< / code > . < code > N::value< / code > must be a nonnegative number. Returns
< code > mp_list< std::integral_constant< T, 0> , std::integral_constant< T, 1> , … ​ , std::integral_constant< T, N::value-1> > < / code >
where < code > T< / code > is the type of < code > N::value< / code > .< / p >
< / div >
2017-06-11 04:35:34 +03:00
< table class = "tableblock frame-all grid-all" style = "width: 85%;" >
< caption class = "title" > Illustration 9. mp_iota< / caption >
< colgroup >
< col style = "width: 50%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< / colgroup >
< tbody >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > mp_iota< mp_int< 4> > < / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > mp_int< 0> < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > mp_int< 1> < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > mp_int< 2> < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > mp_int< 3> < / code > < / p > < / td >
< / tr >
< / tbody >
< / table >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_at_c_l_i" > mp_at_c< L, I> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, std::size_t I> using mp_at_c = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
2017-06-10 03:44:31 +03:00
< p > < code > mp_at_c< L, I> < / code > returns the < code > I< / code > -th element of < code > L< / code > , zero-based.< / p >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_at_l_i" > mp_at< L, I> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, class I> using mp_at = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Same as < code > mp_at_c< / code > , but with a type argument < code > I< / code > . < code > I::value< / code > must be a nonnegative number.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_take_c_l_n" > mp_take_c< L, N> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, std::size_t N> using mp_take_c = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_take_c< L, N> < / code > returns a list of the same type as < code > L< / code > containing the first < code > N< / code > elements of < code > L< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_take_l_n" > mp_take< L, N> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, class N> using mp_take = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Same as < code > mp_take_c< / code > , but with a type argument < code > N< / code > . < code > N::value< / code > must be a nonnegative number.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_insert_c_l_i_t" > mp_insert_c< L, I, T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-09 20:35:21 +03:00
< pre > template< class L, std::size_t I, class... T> using mp_insert_c =
mp_append< mp_take_c< L, I> , mp_push_front< mp_drop_c< L, I> , T...> > ;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > Inserts the elements < code > T… ​ < / code > into the list < code > L< / code > at position < code > I< / code > (a zero-based index).< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_insert_l_i_t" > mp_insert< L, I, T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-09 20:35:21 +03:00
< pre > template< class L, class I, class... T> using mp_insert =
mp_append< mp_take< L, I> , mp_push_front< mp_drop< L, I> , T...> > ;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > Same as < code > mp_insert_c< / code > , but with a type argument < code > I< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_erase_c_l_i_j" > mp_erase_c< L, I, J> < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-09 20:35:21 +03:00
< pre > template< class L, std::size_t I, std::size_t J> using mp_erase_c =
mp_append< mp_take_c< L, I> , mp_drop_c< L, J> > ;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > Removes from the list < code > L< / code > the elements with indices from < code > I< / code > (inclusive) to < code > J< / code > (exclusive).< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_erase_l_i_j" > mp_erase< L, I, J> < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-09 20:35:21 +03:00
< pre > template< class L, class I, class J> using mp_erase =
mp_append< mp_take< L, I> , mp_drop< L, J> > ;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > Same as < code > mp_erase_c< / code > , but with a type arguments < code > I< / code > and < code > J< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_replace_l_v_w" > mp_replace< L, V, W> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, class V, class W> using mp_replace = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Replaces all < code > V< / code > elements of < code > L< / code > with < code > W< / code > and returns the result.< / p >
< / div >
2017-06-11 04:35:34 +03:00
< table class = "tableblock frame-all grid-all" style = "width: 85%;" >
< caption class = "title" > Illustration 10. mp_replace< / caption >
< colgroup >
< col style = "width: 50%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< / colgroup >
< tbody >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > L1< / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > V< / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > n< / sub > < / code > < / p > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > mp_replace< L1, V, W> < / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > W< / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > n< / sub > < / code > < / p > < / td >
< / tr >
< / tbody >
< / table >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_replace_if_l_p_w" > mp_replace_if< L, P, W> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, template< class...> class P, class W> using mp_replace_if = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Replaces all < code > T< / code > elements of < code > L< / code > for which < code > mp_to_bool< P< T> > < / code > is < code > mp_true< / code > with < code > W< / code > and returns the result.< / p >
< / div >
2017-06-11 04:35:34 +03:00
< table class = "tableblock frame-all grid-all" style = "width: 85%;" >
< caption class = "title" > Illustration 11. mp_replace_if< / caption >
< colgroup >
< col style = "width: 50%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< / colgroup >
< tbody >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > L1< / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 2< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > n< / sub > < / code > < / p > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > P< A< sub > i< / sub > > < / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > mp_false< / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > mp_true< / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > mp_false< / code > < / p > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > mp_replace_if< L1, P, W> < / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > W< / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > n< / sub > < / code > < / p > < / td >
< / tr >
< / tbody >
< / table >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_replace_at_c_l_i_w" > mp_replace_at_c< L, I, W> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, std::size_t I, class W> using mp_replace_at_c = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Replaces the element of < code > L< / code > at zero-based index < code > I< / code > with < code > W< / code > and returns the result.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_replace_at_l_i_w" > mp_replace_at< L, I, W> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, class I, class W> using mp_replace_at = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Same as < code > mp_replace_at_c< / code > , but with a type argument < code > I< / code > . < code > I::value< / code > must be a nonnegative number.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_copy_if_l_p" > mp_copy_if< L, P> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, template< class...> class P> using mp_copy_if = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Copies the elements < code > T< / code > of < code > L< / code > for which < code > mp_to_bool< P< T> > < / code > is < code > mp_true< / code > to a new list of the same type and returns it.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_remove_l_v" > mp_remove< L, V> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, class V> using mp_remove = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Removes all < code > V< / code > elements of < code > L< / code > and returns the result.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_remove_if_l_p" > mp_remove_if< L, P> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, template< class...> class P> using mp_remove_if = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Removes all elements < code > T< / code > of < code > L< / code > for which < code > mp_to_bool< P< T> > < / code > is < code > mp_true< / code > and returns the result.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_partition_l_p" > mp_partition< L, P> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, template< class...> class P> using mp_partition = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_partition< L< T… ​ > , P> < / code > partitions < code > L< / code > into two lists < code > L< U1… ​ > < / code > and < code > L< U2… ​ > < / code > such that < code > mp_to_bool< P< T> > < / code > is < code > mp_true< / code >
for the elements of < code > L< U1… ​ > < / code > and < code > mp_false< / code > for the elements of < code > L< U2… ​ > < / code > . Returns < code > L< L< U1… ​ > , L< U2… ​ > > < / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_sort_l_p" > mp_sort< L, P> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, template< class...> class P> using mp_sort = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_sort< L, P> < / code > sorts the list < code > L< / code > according to the strict weak ordering < code > mp_to_bool< P< T, U> > < / code > .< / p >
< / div >
2017-06-09 20:35:21 +03:00
< div class = "listingblock" >
2017-06-10 03:44:31 +03:00
< div class = "title" > Code Example 56. Using mp_sort to sort a list of std::ratio values< / div >
2017-06-09 20:35:21 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre > #include < ratio>
2017-06-09 20:35:21 +03:00
using L1 = mp_list< std::ratio< 1,2> , std::ratio< 1,4> > ;
2017-06-10 03:44:31 +03:00
using R1 = mp_sort< L1, std::ratio_less> ; // mp_list< ratio< 1,4> , ratio< 1,2> > < / pre >
2017-06-09 20:35:21 +03:00
< / div >
< / div >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_find_l_v" > mp_find< L, V> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, class V> using mp_find = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_find< L, V> < / code > returns the index at which the type < code > V< / code > is located in the list < code > L< / code > . It’ s an alias for < code > mp_size_t< I> < / code > ,
where < code > I< / code > is the zero-based index of the first occurence of < code > V< / code > in < code > L< / code > . If < code > L< / code > does not contain < code > V< / code > , < code > mp_find< L, V> < / code >
is < code > mp_size< L> < / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_find_if_l_p" > mp_find_if< L, P> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, template< class...> class P> using mp_find_if = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_find_f< L, P> < / code > is an alias for < code > mp_size_t< I> < / code > , where < code > I< / code > is the zero-based index of the first element < code > T< / code > in < code > L< / code > for which
< code > mp_to_bool< P< T> > < / code > is < code > mp_true< / code > . If there is no such element, < code > mp_find_if< L, P> < / code > is < code > mp_size< L> < / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_reverse_l" > mp_reverse< L> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L> using mp_reverse = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_reverse< L< T1, T2, … ​ , Tn> > < / code > is < code > L< Tn, … ​ , T2, T1> < / code > .< / p >
< / div >
2017-06-11 04:35:34 +03:00
< table class = "tableblock frame-all grid-all" style = "width: 85%;" >
< caption class = "title" > Illustration 12. mp_reverse< / caption >
< colgroup >
< col style = "width: 50%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< col style = "width: 12.5%;" >
< / colgroup >
< tbody >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > L1< / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 2< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > n< / sub > < / code > < / p > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" colspan = "5" > < / td >
< / tr >
< tr >
< td class = "tableblock halign-left valign-middle" > < p class = "tableblock" > < code > < strong > mp_reverse< L1> < / strong > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > n< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > n-1< / sub > < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > … ​ < / code > < / p > < / td >
< td class = "tableblock halign-center valign-middle" > < p class = "tableblock" > < code > A< sub > 1< / sub > < / code > < / p > < / td >
< / tr >
< / tbody >
< / table >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_fold_l_v_f" > mp_fold< L, V, F> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, class V, template< class...> class F> using mp_fold = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_fold< L< T1, T2, … ​ , Tn> , V, F> < / code > is < code > F< F< F< F< V, T1> , T2> , … ​ > , Tn> < / code > , or < code > V< / code > , if < code > L< / code > is empty.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_reverse_fold_l_v_f" > mp_reverse_fold< L, V, F> < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre > template< class L, class V, template< class...> class F> using mp_reverse_fold =
/*...*/;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_reverse_fold< L< T1, T2, … ​ , Tn> , V, F> < / code > is < code > F< T1, F< T2, F< … ​ , F< Tn, V> > > > < / code > , or < code > V< / code > , if < code > L< / code > is empty.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_unique_l" > mp_unique< L> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L> using mp_unique = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_unique< L> < / code > returns a list of the same type as < code > L< / code > with the duplicate elements removed.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_all_of_l_p" > mp_all_of< L, P> < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-09 20:35:21 +03:00
< pre > template< class L, template< class...> class P> using mp_all_of =
mp_bool< mp_count_if< L, P> ::value == mp_size< L> ::value > ;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_all_of< L, P> < / code > is < code > mp_true< / code > when < code > P< / code > holds for all elements of < code > L< / code > , < code > mp_false< / code > otherwise. When < code > L< / code > is empty, the result is < code > mp_true< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_none_of_l_p" > mp_none_of< L, P> < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-09 20:35:21 +03:00
< pre > template< class L, template< class...> class P> using mp_none_of =
mp_bool< mp_count_if< L, P> ::value == 0 > ;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_none_of< L, P> < / code > is < code > mp_true< / code > when < code > P< / code > holds for no element of < code > L< / code > , < code > mp_false< / code > otherwise. When < code > L< / code > is empty, the result is < code > mp_true< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_any_of_l_p" > mp_any_of< L, P> < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-09 20:35:21 +03:00
< pre > template< class L, template< class...> class P> using mp_any_of =
mp_bool< mp_count_if< L, P> ::value != 0 > ;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_any_of< L, P> < / code > is < code > mp_true< / code > when < code > P< / code > holds for at least one element of < code > L< / code > , < code > mp_false< / code > otherwise. When < code > L< / code > is empty, the result is < code > mp_false< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_for_each_l_f" > mp_for_each< L> (f)< / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class L, class F> constexpr F mp_for_each(F& & f);< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_for_each< L> (f)< / code > calls < code > f< / code > with < code > T()< / code > for each element < code > T< / code > of the list < code > L< / code > , in order.< / p >
< / div >
< div class = "paragraph" >
< p > Returns < code > std::forward< F> (f)< / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 57. Using mp_for_each and a C++14 lambda to print a tuple< / div >
< div class = "content" >
< pre class = "highlight" > < code > template< class... T> void print( std::tuple< T...> const & tp )
{
std::size_t const N = sizeof...(T);
mp_for_each< mp_iota_c< N> > ( []( auto I ){
// I is mp_size_t< 0> , mp_size_t< 1> , ..., mp_size_t< N-1>
std::cout < < std::get< I> (tp) < < std::endl;
});
}< / code > < / pre >
< / div >
< / div >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "sect3" >
< h4 id = "mp_with_index_n_i_f" > mp_with_index< N> (i, f)< / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre > template< std::size_t N, class F>
constexpr auto mp_with_index( std::size_t i, F & & f )
-> decltype(std::declval< F> ()(std::declval< mp_size_t< 0> > ()));< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
2017-06-10 03:44:31 +03:00
< p > < code > mp_with_index< N> (i, f)< / code > calls < code > f< / code > with < code > mp_size_t< i> ()< / code > and returns the result. < code > i< / code > must be less than < code > N< / code > .
Only < code > constexpr< / code > on C++14 and higher.< / p >
2017-06-07 00:02:25 +03:00
< / div >
< div class = "literalblock" >
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre > template< class N, class F>
constexpr auto mp_with_index( std::size_t i, F & & f )
-> decltype(std::declval< F> ()(std::declval< mp_size_t< 0> > ()));< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > Returns < code > mp_with_index< N::value> (i, f)< / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 58. Using mp_with_index and a C++14 lambda to print the active element of a variant< / div >
< div class = "content" >
< pre class = "highlight" > < code > template< class... T> void print( std::variant< T...> const& v )
{
mp_with_index< sizeof...(T)> ( v.index(), [& ]( auto I ) {
// I is mp_size_t< v.index()> here
std::cout < < std::get< I> ( v ) < < std::endl;
});
}< / code > < / pre >
< / div >
< / div >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "sect2" >
< h3 id = "set" > Set Operations, < boost/mp11/set.hpp> < / h3 >
< div class = "paragraph" >
< p > A set is a list whose elements are unique.< / p >
< / div >
< div class = "sect3" >
< h4 id = "mp_set_contains_s_v" > mp_set_contains< S, V> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class S, class V> using mp_set_contains = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_set_contains< S, V> < / code > is < code > mp_true< / code > if the type < code > V< / code > is an element of the set < code > S< / code > , < code > mp_false< / code > otherwise.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_set_push_back_s_t" > mp_set_push_back< S, T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class S, class... T> using mp_set_push_back = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > For each < code > T1< / code > in < code > T… ​ < / code > , < code > mp_set_push_back< S, T… ​ > < / code > appends < code > T1< / code > to the end of < code > S< / code > if it’ s not already an element of < code > S< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_set_push_front_s_t" > mp_set_push_front< S, T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class S, class... T> using mp_set_push_front = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_set_push_front< S, T… ​ > < / code > inserts at the front of < code > S< / code > those elements of < code > T… ​ < / code > for which < code > S< / code > does not already contain the same type.< / p >
< / div >
< / div >
< / div >
< div class = "sect2" >
< h3 id = "map" > Map Operations, < boost/mp11/map.hpp> < / h3 >
< div class = "paragraph" >
< p > A map is a list of lists, the inner lists having at least one element (the key.) The keys of the map must be unique.< / p >
< / div >
< div class = "sect3" >
< h4 id = "mp_map_find_m_k" > mp_map_find< M, K> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class M, class K> using mp_map_find = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_map_find< M, K> < / code > is an alias for the element of the map < code > M< / code > with a key < code > K< / code > , or for < code > void< / code > , if there is no such element.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_map_contains_m_k" > mp_map_contains< M, K> < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre > template< class M, class K> using mp_map_contains =
mp_not< std::is_same< mp_map_find< M, K> , void> > ;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_map_contains< M, K> < / code > is < code > mp_true< / code > if the map < code > M< / code > contains an element with a key < code > K< / code > , < code > mp_false< / code > otherwise.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_map_insert_m_t" > mp_map_insert< M, T> < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-09 20:35:21 +03:00
< pre > template< class M, class T> using mp_map_insert =
mp_if< mp_map_contains< M, mp_first< T> > , M, mp_push_back< M, T> > ;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > Inserts the element < code > T< / code > into the map < code > M< / code > , if an element with a key < code > mp_first< T> < / code > is not already in < code > M< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_map_replace_m_t" > mp_map_replace< M, T> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class M, class T> using mp_map_replace = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > If the map < code > M< / code > does not contain an element with a key < code > mp_first< T> < / code > , inserts it (using < code > mp_push_back< M, T> < / code > ); otherwise,
replaces the existing element with < code > T< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_map_update_m_t_f" > mp_map_update< M, T, F> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class M, class T, template< class...> class F> using mp_map_update = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > If the map < code > M< / code > does not contain an element with a key < code > mp_first< T> < / code > , inserts it (using < code > mp_push_back< M, T> < / code > ); otherwise,
replaces the existing element < code > L< X, Y… ​ > < / code > with < code > L< X, F< X, Y… ​ > > < / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_map_erase_m_k" > mp_map_erase< M, K> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class M, class K> using mp_map_erase = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > If the map < code > M< / code > contains an element with a key < code > K< / code > , removes it.< / p >
< / div >
< / div >
< / div >
< div class = "sect2" >
< h3 id = "function" > Helper Metafunctions, < boost/mp11/function.hpp> < / h3 >
< div class = "sect3" >
< h4 id = "mp_void_t" > mp_void< T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class... T> using mp_void = void;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > Same as < code > std::void_t< / code > from C++17.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_and_t" > mp_and< T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class... T> using mp_and = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_and< T… ​ > < / code > applies < code > mp_to_bool< / code > to the types in < code > T… ​ < / code > , in order. If the result of an application is < code > mp_false< / code > , < code > mp_and< / code >
returns < code > mp_false< / code > . If the application causes a substitution failure, returns < code > mp_false< / code > . If all results are < code > mp_true< / code > ,
returns < code > mp_true< / code > . < code > mp_and< > < / code > is < code > mp_true< / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 59. mp_and behavior< / div >
2017-06-09 20:35:21 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using R1 = mp_and< mp_true, mp_true> ; // mp_true
using R2 = mp_and< mp_false, void> ; // mp_false, void is not reached
using R3 = mp_and< mp_false, mp_false> ; // mp_false
using R4 = mp_and< void, mp_true> ; // mp_false (!)< / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_all_t" > mp_all< T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class... T> using mp_all = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_all< T… ​ > < / code > is < code > mp_true< / code > if < code > mp_to_bool< U> < / code > is < code > mp_true< / code > for all types < code > U< / code > in < code > T… ​ < / code > , < code > mp_false< / code > otherwise. Same as
< code > mp_and< / code > , but does not perform short-circuit evaluation. < code > mp_and< mp_false, void> < / code > is < code > mp_false< / code > , but < code > mp_all< mp_false, void> < / code >
is an error because < code > void< / code > does not have a nested < code > value< / code > . The upside is that < code > mp_all< / code > is potentially faster and does not
mask substitution failures as < code > mp_and< / code > does.< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 60. mp_all behavior< / div >
2017-06-09 20:35:21 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using R1 = mp_all< mp_true, mp_true> ; // mp_true
using R2 = mp_all< mp_false, void> ; // compile-time error
using R3 = mp_all< mp_false, mp_false> ; // mp_false
using R4 = mp_all< void, mp_true> ; // compile-time error< / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_or_t" > mp_or< T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class... T> using mp_or = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_or< T… ​ > < / code > applies < code > mp_to_bool< / code > to the types in < code > T… ​ < / code > , in order. If the result of an application is < code > mp_true< / code > , < code > mp_or< / code >
returns < code > mp_true< / code > . If all results are < code > mp_false< / code > , returns < code > mp_false< / code > . < code > mp_or< > < / code > is < code > mp_false< / code > .< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 61. mp_or behavior< / div >
2017-06-09 20:35:21 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using R1 = mp_or< mp_true, mp_false> ; // mp_true
using R2 = mp_or< mp_true, void> ; // mp_true, void is not reached
using R3 = mp_or< mp_false, mp_false> ; // mp_false
using R4 = mp_or< void, mp_true> ; // compile-time error< / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_any_t" > mp_any< T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class... T> using mp_any = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_any< T… ​ > < / code > is < code > mp_true< / code > if < code > mp_to_bool< U> < / code > is < code > mp_true< / code > for any type < code > U< / code > in < code > T… ​ < / code > , < code > mp_false< / code > otherwise. Same as
< code > mp_or< / code > , but does not perform short-circuit evaluation.< / p >
< / div >
2017-06-10 03:44:31 +03:00
< div class = "listingblock" >
< div class = "title" > Code Example 62. mp_any behavior< / div >
2017-06-07 00:02:25 +03:00
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre class = "highlight" > < code > using R1 = mp_any< mp_true, mp_false> ; // mp_true
using R2 = mp_any< mp_true, void> ; // compile-time error
using R3 = mp_any< mp_false, mp_false> ; // mp_false
using R4 = mp_any< void, mp_true> ; // compile-time error< / code > < / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_same_t" > mp_same< T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class... T> using mp_same = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_same< T… ​ > < / code > is < code > mp_true< / code > if all the types in < code > T… ​ < / code > are the same type, < code > mp_false< / code > otherwise. < code > mp_same< > < / code > is < code > mp_true< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_plus_t" > mp_plus< T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class... T> using mp_plus = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_plus< T… ​ > < / code > is an integral constant type with a value that is the sum of < code > U::value< / code > for all types < code > U< / code > in < code > T… ​ < / code > .
< code > mp_plus< > < / code > is < code > mp_int< 0> < / code > .< / p >
< / div >
< / div >
< / div >
< div class = "sect2" >
< h3 id = "bind" > Bind, < boost/mp11/bind.hpp> < / h3 >
< div class = "sect3" >
< h4 id = "mp_arg_i" > mp_arg< I> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< std::size_t I> struct mp_arg;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_arg< I> < / code > is a quoted metafunction whose nested template < code > fn< T… ​ > < / code > returns the < code > I< / code > -th zero-based element of < code > T… ​ < / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "1_9" > _1, … ​ , _9< / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > using _1 = mp_arg< 0> ;
using _2 = mp_arg< 1> ;
using _3 = mp_arg< 2> ;
using _4 = mp_arg< 3> ;
using _5 = mp_arg< 4> ;
using _6 = mp_arg< 5> ;
using _7 = mp_arg< 6> ;
using _8 = mp_arg< 7> ;
using _9 = mp_arg< 8> ;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > _1< / code > to < code > _9< / code > are placeholder types, the equivalent to the placeholders of < code > boost::bind< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_bind_f_t" > mp_bind< F, T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< template< class...> class F, class... T> struct mp_bind;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_bind< F, T… ​ > < / code > is a quoted metafunction that implements the type-based equivalent of < code > boost::bind< / code > . Its nested
template < code > fn< U… ​ > < / code > returns < code > F< V… ​ > < / code > , where < code > V… ​ < / code > is < code > T… ​ < / code > with the placeholders replaced by the corresponding element
of < code > U… ​ < / code > and the < code > mp_bind< / code > expressions replaced with their corresponding evaluations against < code > U… ​ < / code > .< / p >
< / div >
< div class = "paragraph" >
< p > For example, < code > mp_bind< F, int, _2, mp_bind< G, _1> > ::fn< float, void> < / code > is < code > F< int, void, G< float> > < / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_bind_q_q_t" > mp_bind_q< Q, T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class Q, class... T> using mp_bind_q = mp_bind< Q::template fn, T...> ;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > As < code > mp_bind< / code > , but takes a quoted metafunction.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_bind_front_f_t" > mp_bind_front< F, T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< template< class...> class F, class... T> struct mp_bind_front;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_bind_front< F, T… ​ > < / code > binds the leftmost arguments of < code > F< / code > to < code > T… ​ < / code > . Its nested template < code > fn< U… ​ > < / code > returns < code > F< T… ​ , U… ​ > < / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_bind_front_q_q_t" > mp_bind_front_q< Q, T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre > template< class Q, class... T> using mp_bind_front_q =
mp_bind_front< Q::template fn, T...> ;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > As < code > mp_bind_front< / code > , but takes a quoted metafunction.< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_bind_back_f_t" > mp_bind_back< F, T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< template< class...> class F, class... T> struct mp_bind_back;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > mp_bind_back< F, T… ​ > < / code > binds the rightmost arguments of < code > F< / code > to < code > T… ​ < / code > . Its nested template < code > fn< U… ​ > < / code > returns < code > F< U… ​ , T… ​ > < / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "mp_bind_back_q_q_t" > mp_bind_back_q< Q, T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre > template< class Q, class... T> using mp_bind_back_q =
mp_bind_back< Q::template fn, T...> ;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > As < code > mp_bind_back< / code > , but takes a quoted metafunction.< / p >
< / div >
< / div >
< / div >
< div class = "sect2" >
< h3 id = "integer_sequence" > Integer Sequences, < boost/mp11/integer_sequence.hpp> < / h3 >
< div class = "sect3" >
< h4 id = "integer_sequence_t_i" > integer_sequence< T, I… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class T, T... I> struct integer_sequence
{
};< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > integer_sequence< T, I… ​ > < / code > holds a sequence of integers of type < code > T< / code > . Same as C++14’ s < code > std::integer_sequence< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "make_integer_sequence_t_n" > make_integer_sequence< T, N> < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class T, T N> using make_integer_sequence = /*...*/;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > make_integer_sequence< T, N> < / code > is < code > integer_sequence< T, 0, 1, … ​ , N-1> < / code > . Same as C++14’ s < code > std::make_integer_sequence< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "index_sequence_i" > index_sequence< I… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< std::size_t... I> using index_sequence = integer_sequence< std::size_t, I...> ;< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > index_sequence< I… ​ > < / code > is an alias for < code > integer_sequence< size_t, I… ​ > < / code > . Same as C++14’ s < code > std::index_sequence< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "make_index_sequence_n" > make_index_sequence< N> < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre > template< std::size_t N> using make_index_sequence =
make_integer_sequence< std::size_t, N> ;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > < code > make_index_sequence< N> < / code > is < code > index_sequence< 0, 1, … ​ , N-1> < / code > . Same as C++14’ s < code > std::make_index_sequence< / code > .< / p >
< / div >
< / div >
< div class = "sect3" >
< h4 id = "index_sequence_for_t" > index_sequence_for< T… ​ > < / h4 >
< div class = "literalblock" >
< div class = "content" >
2017-06-10 03:44:31 +03:00
< pre > template< class... T> using index_sequence_for =
make_integer_sequence< std::size_t, sizeof...(T)> ;< / pre >
2017-06-07 00:02:25 +03:00
< / div >
< / div >
< div class = "paragraph" >
< p > < code > index_sequence_for< N> < / code > is < code > make_index_sequence< sizeof… ​ (T)> < / code > . Same as C++14’ s < code > std::index_sequence_for< / code > .< / p >
< / div >
< / div >
< / div >
< div class = "sect2" >
2017-06-08 16:35:55 +03:00
< h3 id = "tuple" > Tuple Operations, < boost/mp11/tuple.hpp> < / h3 >
2017-06-07 00:02:25 +03:00
< div class = "sect3" >
2017-06-08 17:19:28 +03:00
< h4 id = "tuple_apply_f_tp" > tuple_apply(f, tp)< / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class F, class Tp> constexpr /*...*/ tuple_apply(F& & f, Tp& & tp);< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > tuple_apply(f, tp)< / code > returns < code > std::forward< F> (f)(std::get< J> (std::forward< Tp> (tp))… ​ )< / code > for < code > J< / code > in 0..< code > N-1< / code > ,
where < code > N< / code > is < code > std::tuple_size< typename std::remove_reference< Tp> ::type> ::value< / code > . Same as < code > std::apply< / code > in C++17.< / p >
< / div >
< / div >
< div class = "sect3" >
2017-06-08 19:22:53 +03:00
< h4 id = "construct_from_tuple_t_tp" > construct_from_tuple< T> (tp)< / h4 >
2017-06-08 17:42:50 +03:00
< div class = "literalblock" >
< div class = "content" >
2017-06-08 19:22:53 +03:00
< pre > template< class T, class Tp> T construct_from_tuple(Tp& & tp);< / pre >
2017-06-08 17:42:50 +03:00
< / div >
< / div >
< div class = "paragraph" >
2017-06-08 19:22:53 +03:00
< p > < code > construct_from_tuple< T> (tp)< / code > returns < code > T(std::get< J> (std::forward< Tp> (tp))… ​ )< / code > for < code > J< / code > in 0..< code > N-1< / code > ,
where < code > N< / code > is < code > std::tuple_size< typename std::remove_reference< Tp> ::type> ::value< / code > . Same as < code > std::make_from_tuple< / code > in C++17.
The name of the function doesn’ t match the C++17 one to avoid ambiguities when both are visible or in unqualified calls.< / p >
2017-06-08 17:42:50 +03:00
< / div >
< / div >
< div class = "sect3" >
2017-06-07 00:02:25 +03:00
< h4 id = "tuple_for_each_tp_f" > tuple_for_each(tp, f)< / h4 >
< div class = "literalblock" >
< div class = "content" >
< pre > template< class Tp, class F> constexpr F tuple_for_each(Tp& & tp, F& & f);< / pre >
< / div >
< / div >
< div class = "paragraph" >
< p > < code > tuple_for_each(tp, f)< / code > applies the function object < code > f< / code > to each element of < code > tp< / code > by evaluating the
expression < code > f(std::get< J> (std::forward< Tp> (tp)))< / code > for < code > J< / code > in 0..< code > N-1< / code > , where < code > N< / code > is < code > std::tuple_size< typename std::remove_reference< Tp> ::type> ::value< / code > .< / p >
< / div >
< div class = "paragraph" >
< p > Returns < code > std::forward< F> (f)< / code > .< / p >
< / div >
< / div >
< / div >
< / div >
< / div >
< div class = "sect1" >
< h2 id = "copyright_and_license" > Appendix A: Copyright and License< / h2 >
< div class = "sectionbody" >
< div class = "paragraph" >
< p > This documentation is< / p >
< / div >
< div class = "ulist" >
< ul >
< li >
< p > Copyright 2017 Peter Dimov< / p >
< / li >
< li >
< p > Distributed under the < a href = "http://www.boost.org/LICENSE_1_0.txt" > Boost Software License, Version 1.0< / a > .< / p >
< / li >
< / ul >
< / div >
< / div >
< / div >
< / div >
< div id = "footer" >
< div id = "footer-text" >
2017-06-11 04:35:34 +03:00
Last updated 2017-06-11 03:50:25 GTBDT
2017-06-07 00:02:25 +03:00
< / div >
< / div >
2017-06-11 04:35:34 +03:00
< style >
*:not(pre)>code { background: none; color: #600000; }
table tr.even, table tr.alt, table tr:nth-of-type(even) { background: none; }
< / style >
< script >
var header = document.getElementById( 'boost-common-heading-doc' );
if( header )
{
header.style.position = 'fixed';
header.style.zIndex = '100';
var notice = document.getElementsByClassName( 'boost-common-header-notice' )[ 0 ];
if( notice )
{
notice.style.position = 'fixed';
notice.style.zIndex = '101';
}
var toc = document.getElementById( 'toc' );
if( toc )
{
toc.style.top = '101px';
}
}
< / script >
2017-03-14 22:57:07 +02:00
< / body >
2017-06-07 00:02:25 +03:00
< / html >