Files
openmethod/doc/html/index.html
2025-10-05 19:15:54 -04:00

6257 lines
221 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.20">
<meta name="author" content="Jean-Louis Leroy">
<title>Boost.OpenMethod</title>
<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 | https://asciidoctor.org */
/* Uncomment the following line 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"; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{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}
audio,video{display:inline-block}
audio:not([controls]){display:none;height: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]{padding:0}
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{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;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-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%}
.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}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{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 #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
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{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
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}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media 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:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
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{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{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}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre>code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
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:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;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,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
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:0 auto;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 #dddddf}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;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 #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;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 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:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#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 #e7e7e9;left:auto;right:0}}
@media 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:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#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}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details>summary::-webkit-details-marker{display:none}
details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.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.fit-content>caption.title{white-space:nowrap;width:0}
.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.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 #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child,.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,.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>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.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:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.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:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;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 blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock>.content>:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all>*>tr>*{border-width:1px}
table.grid-cols>*>tr>*{border-width:0 1px}
table.grid-rows>*>tr>*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}
table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
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{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}
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}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li>p:empty:only-child::before{content:"";display:inline-block}
ul.checklist>li>p:first-child{margin-left:-1em}
ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline>li{margin-left:1.25em}
.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}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.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;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
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:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon>.fa{cursor:default}
a span.icon>.fa{cursor:inherit}
.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:rgba(0,0,0,.8);border-radius:50%;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,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
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]{border-bottom:1px dotted}
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}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
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{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
</style>
</head>
<body class="article toc2 toc-left">
<div id="header">
<h1>Boost.OpenMethod</h1>
<div class="details">
<span id="author" class="author">Jean-Louis Leroy</span><br>
</div>
<div id="toc" class="toc2">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#introduction">Introduction</a></li>
<li><a href="#tutorials">Tutorials</a>
<ul class="sectlevel2">
<li><a href="#tutorials_hello_world">Hello World</a></li>
<li><a href="#tutorials_multiple_dispatch">Multiple Dispatch</a></li>
<li><a href="#tutorials_headers_and_namespaces">Headers and Namespaces</a></li>
<li><a href="#tutorials_friendship">Friendship</a></li>
<li><a href="#tutorials_performance">Performance</a></li>
<li><a href="#tutorials_smart_pointers">Smart Pointers</a></li>
<li><a href="#tutorials_alternatives_to_virtual_ptr">Alternatives to virtual_ptr</a></li>
<li><a href="#tutorials_core_api">Core API</a></li>
<li><a href="#tutorials_policies_and_policys">Policies and Facets</a></li>
<li><a href="#tutorials_error_handling">Error Handling</a></li>
<li><a href="#tutorials_custom_rtti">Custom RTTI</a></li>
<li><a href="#tutorials_deferred_rtti">Deferred RTTI</a></li>
<li><a href="#tutorials_dynamic_loading">Dynamic Loading</a></li>
</ul>
</li>
<li><a href="#tutorials_reference">Reference</a>
<ul class="sectlevel2">
<li><a href="#ref_overview">Overview</a>
<ul class="sectlevel3">
<li><a href="#ref_requirements">Requirements</a></li>
<li><a href="#ref_installation">Installation</a></li>
<li><a href="#ref_namespaces">Namespaces</a></li>
<li><a href="#ref_headers">Headers</a></li>
</ul>
</li>
<li><a href="#BOOST_OPENMETHOD">BOOST_OPENMETHOD</a>
<ul class="sectlevel3">
<li><a href="#ref_synopsis">Synopsis</a></li>
<li><a href="#ref_description">Description</a></li>
</ul>
</li>
<li><a href="#BOOST_OPENMETHOD_OVERRIDE">BOOST_OPENMETHOD_OVERRIDE</a>
<ul class="sectlevel3">
<li><a href="#ref_synopsis_2">Synopsis</a></li>
<li><a href="#ref_description_2">Description</a></li>
</ul>
</li>
<li><a href="#BOOST_OPENMETHOD_INLINE_OVERRIDE">BOOST_OPENMETHOD_INLINE_OVERRIDE</a>
<ul class="sectlevel3">
<li><a href="#ref_synopsis_3">Synopsis</a></li>
<li><a href="#ref_description_3">Description</a></li>
</ul>
</li>
<li><a href="#ref_boost_openmethod_declare_overrider">BOOST_OPENMETHOD_DECLARE_OVERRIDER</a>
<ul class="sectlevel3">
<li><a href="#ref_synopsis_4">Synopsis</a></li>
<li><a href="#ref_description_4">Description</a></li>
</ul>
</li>
<li><a href="#ref_boost_openmethod_define_overrider">BOOST_OPENMETHOD_DEFINE_OVERRIDER</a>
<ul class="sectlevel3">
<li><a href="#ref_synopsis_5">Synopsis</a></li>
<li><a href="#ref_description_5">Description</a></li>
</ul>
</li>
<li><a href="#ref_boost_openmethod_overrider">BOOST_OPENMETHOD_OVERRIDER</a>
<ul class="sectlevel3">
<li><a href="#ref_synopsis_6">Synopsis</a></li>
<li><a href="#ref_description_6">Description</a></li>
</ul>
</li>
<li><a href="#BOOST_OPENMETHOD_ID">BOOST_OPENMETHOD_ID</a>
<ul class="sectlevel3">
<li><a href="#ref_synopsis_7">Synopsis</a></li>
<li><a href="#ref_description_7">Description</a></li>
</ul>
</li>
<li><a href="#ref_boost_openmethod_guide">BOOST_OPENMETHOD_GUIDE</a>
<ul class="sectlevel3">
<li><a href="#ref_synopsis_8">Synopsis</a></li>
<li><a href="#ref_description_8">Description</a></li>
</ul>
</li>
<li><a href="#ref_boost_openmethod_overriders">BOOST_OPENMETHOD_OVERRIDERS</a>
<ul class="sectlevel3">
<li><a href="#ref_synopsis_9">Synopsis</a></li>
<li><a href="#ref_description_9">Description</a></li>
</ul>
</li>
<li><a href="#BOOST_OPENMETHOD_REGISTER">BOOST_OPENMETHOD_REGISTER</a>
<ul class="sectlevel3">
<li><a href="#ref_synopsis_10">Synopsis</a></li>
<li><a href="#ref_description_10">Description</a></li>
</ul>
</li>
<li><a href="#BOOST_OPENMETHOD_CLASSES">BOOST_OPENMETHOD_CLASSES</a>
<ul class="sectlevel3">
<li><a href="#ref_synopsis_11">Synopsis</a></li>
<li><a href="#ref_description_11">Description</a></li>
</ul>
</li>
<li><a href="#BOOST_OPENMETHOD_DEFAULT_REGISTRY">BOOST_OPENMETHOD_DEFAULT_REGISTRY</a>
<ul class="sectlevel3">
<li><a href="#ref_description_12">Description</a></li>
</ul>
</li>
<li><a href="#ref_initialize">initialize</a>
<ul class="sectlevel3">
<li><a href="#ref_synopsis_12">Synopsis</a></li>
<li><a href="#ref_description_13">Description</a></li>
</ul>
</li>
<li><a href="#ref_finalize">finalize</a>
<ul class="sectlevel3">
<li><a href="#ref_synopsis_13">Synopsis</a></li>
<li><a href="#ref_description_14">Description</a></li>
</ul>
</li>
<li><a href="#ref_type_id">type_id</a>
<ul class="sectlevel3">
<li><a href="#ref_synopsis_14">Synopsis</a></li>
<li><a href="#ref_description_15">Description</a></li>
</ul>
</li>
<li><a href="#ref_vptr_type">vptr_type</a>
<ul class="sectlevel3">
<li><a href="#ref_synopsis_15">Synopsis</a></li>
<li><a href="#ref_description_16">Description</a></li>
</ul>
</li>
<li><a href="#ref_method">method</a>
<ul class="sectlevel3">
<li><a href="#ref_synopsis_16">Synopsis</a></li>
<li><a href="#ref_description_17">Description</a></li>
<li><a href="#ref_members">Members</a></li>
</ul>
</li>
<li><a href="#method_override">method::override</a>
<ul class="sectlevel3">
<li><a href="#ref_synopsis_17">Synopsis</a></li>
<li><a href="#ref_description_18">Description</a></li>
<li><a href="#ref_members_2">Members</a></li>
</ul>
</li>
<li><a href="#virtual_ptr">virtual_ptr</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis">Synopsis</a></li>
<li><a href="#virtual_ptr_description">Description</a></li>
<li><a href="#virtual_ptr_members">Members</a></li>
<li><a href="#virtual_ptr_deduction_guide">Deduction guide</a></li>
<li><a href="#virtual_ptr_non_members">Non-members</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_virtual_traits">virtual_traits</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_2">Synopsis</a></li>
<li><a href="#virtual_ptr_description_2">Description</a></li>
<li><a href="#virtual_ptr_specializations">Specializations</a></li>
<li><a href="#virtual_ptr_members_2">Members</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_use_classes">use_classes</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_3">Synopsis</a></li>
<li><a href="#virtual_ptr_description_3">Description</a></li>
<li><a href="#virtual_ptr_members_3">Members</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_virtual">virtual_</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_4">Synopsis</a></li>
<li><a href="#virtual_ptr_description_4">Description</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_inplace_vptr">inplace_vptr</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_5">Synopsis</a></li>
<li><a href="#virtual_ptr_description_5">Description</a></li>
<li><a href="#virtual_ptr_members_4">Members</a></li>
<li><a href="#virtual_ptr_synopsis_6">Synopsis</a></li>
<li><a href="#virtual_ptr_description_6">Description</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_domain">domain</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_7">Synopsis</a></li>
<li><a href="#virtual_ptr_description_7">Description</a></li>
<li><a href="#virtual_ptr_members_5">Members</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_basic_policy">basic_policy</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_8">Synopsis</a></li>
<li><a href="#virtual_ptr_headers">Headers</a></li>
<li><a href="#virtual_ptr_description_8">Description</a></li>
<li><a href="#virtual_ptr_members_6">Members</a></li>
<li><a href="#virtual_ptr_non_members_2">Non-members</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_policy">policy</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_9">Synopsis</a></li>
<li><a href="#virtual_ptr_description_9">Description</a></li>
<li><a href="#virtual_ptr_members_7">Members</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_rtti">rtti</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_10">Synopsis</a></li>
<li><a href="#virtual_ptr_description_10">Description</a></li>
<li><a href="#virtual_ptr_requirements">Requirements</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_std_rtti">std_rtti</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_11">Synopsis</a></li>
<li><a href="#virtual_ptr_description_11">Description</a></li>
<li><a href="#virtual_ptr_members_8">Members</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_deferred_static_rtti">deferred_static_rtti</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_12">Synopsis</a></li>
<li><a href="#virtual_ptr_description_12">Description</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_minimal_rtti">minimal_rtti</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_13">Synopsis</a></li>
<li><a href="#virtual_ptr_description_13">Description</a></li>
<li><a href="#virtual_ptr_members_9">Members</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_extern_vptr">extern_vptr</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_14">Synopsis</a></li>
<li><a href="#virtual_ptr_description_14">Description</a></li>
<li><a href="#virtual_ptr_requirements_2">Requirements</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_indirect_vptr">indirect_vptr</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_15">Synopsis</a></li>
<li><a href="#virtual_ptr_description_15">Description</a></li>
<li><a href="#virtual_ptr_requirements_3">Requirements</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_vptr_vector">vptr_vector</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_16">Synopsis</a></li>
<li><a href="#virtual_ptr_description_16">Description</a></li>
<li><a href="#virtual_ptr_members_10">Members</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_vptr_map">vptr_map</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_17">Synopsis</a></li>
<li><a href="#virtual_ptr_description_17">Description</a></li>
<li><a href="#virtual_ptr_members_11">Members</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_type_hash">type_hash</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_18">Synopsis</a></li>
<li><a href="#virtual_ptr_description_18">Description</a></li>
<li><a href="#virtual_ptr_requirements_4">Requirements</a></li>
<li><a href="#virtual_ptr_hash_type_id">hash_type_id</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_fast_perfect_hash">fast_perfect_hash</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_19">Synopsis</a></li>
<li><a href="#virtual_ptr_description_19">Description</a></li>
<li><a href="#virtual_ptr_members_12">Members</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_error_handler">error_handler</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_20">Synopsis</a></li>
<li><a href="#virtual_ptr_description_20">Description</a></li>
<li><a href="#virtual_ptr_requirements_5">Requirements</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_default_error_handler">default_error_handler</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_21">Synopsis</a></li>
<li><a href="#virtual_ptr_description_21">Description</a></li>
<li><a href="#virtual_ptr_members_13">Members</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_throw_error_handler">throw_error_handler</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_22">Synopsis</a></li>
<li><a href="#virtual_ptr_description_22">Description</a></li>
<li><a href="#virtual_ptr_members_14">Members</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_basic_error_output">basic_error_output</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_23">Synopsis</a></li>
<li><a href="#virtual_ptr_description_23">Description</a></li>
<li><a href="#virtual_ptr_members_15">Members</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_basic_trace_output">basic_trace_output</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_synopsis_24">Synopsis</a></li>
<li><a href="#virtual_ptr_description_24">Description</a></li>
<li><a href="#virtual_ptr_members_16">Members</a></li>
</ul>
</li>
<li><a href="#virtual_ptr_restrictedoutputstream">LightweightOutputStream</a>
<ul class="sectlevel3">
<li><a href="#virtual_ptr_description_25">Description</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
<div id="content">
<div class="sect1">
<h2 id="introduction">Introduction</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Open-methods are similar to virtual functions, but they are not required to be
members of a class. By being both free and virtual, they provide a solution to
the Expression Problem:</p>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>Given a set of types, and a set of operations on these types, is it possible
to add new operations on the existing types, and new types to the existing
operations, without modifying existing code?</p>
</div>
</blockquote>
</div>
<div class="paragraph">
<p>Open-methods also address the banana-gorilla-shared problem:</p>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>The problem with object-oriented languages is theyve got all this implicit
environment that they carry around with them. You wanted a banana but what you
got was a gorilla holding the banana and the entire shared. — Joe Armstrong,
creator of Erlang progamming language</p>
</div>
</blockquote>
</div>
<div class="paragraph">
<p>As a bonus, open-methods can take more than one argument into account when
selecting the appropriate function to call - aka multiple dispatch. For that
reason, open-methods are often called multi-methods, but that term is
misleading, as it suggests that the feature is useful only when multiple
dispatch is needed. In reality,
<a href="https://openaccess.wgtn.ac.nz/articles/thesis/Multiple_Dispatch_in_Practice/16959112/1">it
has been observed</a> that, in large systems written in languages that support
multi-methods, most methods use single-dispatch. The real benefit is in the
solution to the Expression Problem.</p>
</div>
<div class="paragraph">
<p>Open-methods were introduced by the Common Lisp Object System, and they are
native to many languages: Clojure, Julia, Dylan, TADS, Cecil, Diesel, Nice, etc.
Bjarne Stroustrup wanted open-methods in C++ almost from the beginning. In D&amp;E
he writes:</p>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>I repeatedly considered a mechanism for a virtual function call based on more
than one object, often called multi-methods. I rejected multi-methods with
regret because I liked the idea, but couldnt find an acceptable form under
which to accept it. [&#8230;&#8203;] Multi-methods is one of the interesting what-ifs of
C++. Could I have designed and implemented them well enough at the time? Would
their applications have been important enough to warrant the effort? What other
work might have been left undone to provide the time to design and implement
multi-methods? Since about 1985, I have always felt some twinge of regret for
not providing multi-methods (Stroustrup, 1994, The Design and Evolution of
C&#43;&#43;, 13.8).</p>
</div>
</blockquote>
</div>
<div class="paragraph">
<p>Circa 2007, he and his PhD students Peter Pirkelbauer and Yuriy Solodkyy wrote a
series of papers and a prototype implementation based on the EDG compiler.
Unfortunately, open-methods never made it into the standard. Stroustrup bemoans,
in a more recent paper:</p>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>In retrospect, I dont think that the object-oriented notation (e.g., x.f(y))
should ever have been introduced. The traditional mathematical notation f(x,y)
is sufficient. As a side benefit, the mathematical notation would naturally have
given us multi-methods, thereby saving us from the visitor pattern workaround
(Stroustrup, 2020, Thriving in a Crowded and ChangingWorld: C++ 20062020).</p>
</div>
</blockquote>
</div>
<div class="paragraph">
<p>This library implements the features described in the
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2216.pdf">N2216 paper</a>,
with some extensions:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>a mechanism for calling the next most specialized overrider</p>
</li>
<li>
<p>support for smart pointers</p>
</li>
<li>
<p>customization points for RTTI, error handling, tracing, smart pointers&#8230;&#8203;</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Multiple and virtual inheritance are supported, with the exception of repeated
inheritance.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="tutorials">Tutorials</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="tutorials_hello_world">Hello World</h3>
<div class="paragraph">
<p>Consider the following program, intended to demonstrate the basics of virtual
functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#include &lt;iostream&gt;
#include &lt;memory&gt;
struct Animal {
Animal(std::string name) : name(name) {}
virtual ~Animal() = default;
virtual void poke(std::ostream&amp;) = 0;
std::string name;
};
struct Cat : Animal {
using Animal::Animal;
void poke(std::ostream&amp; os) override {
os &lt;&lt; name &lt;&lt; " hisses";
}
};
struct Dog : Animal {
using Animal::Animal;
void poke(std::ostream&amp; os) override {
os &lt;&lt; name &lt;&lt; " barks";
}
};
struct Bulldog : Dog {
using Dog::Dog;
void poke(std::ostream&amp; os) override {
Dog::poke(os);
os &lt;&lt; " and bites back";
}
};
auto main() -&gt; int {
std::unique_ptr&lt;Animal&gt; a(new Cat("Felix"));
std::unique_ptr&lt;Animal&gt; b(new Dog("Snoopy"));
std::unique_ptr&lt;Animal&gt; c(new Bulldog("Hector"));
a-&gt;poke(std::cout); // prints "Felix hisses"
std::cout &lt;&lt; ".\n";
b-&gt;poke(std::cout); // prints "Snoopy barks"
std::cout &lt;&lt; ".\n";
c-&gt;poke(std::cout); // prints "Hector barks and bites back"
std::cout &lt;&lt; ".\n";
return 0;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>We are going to rewrite this using open-methods.</p>
</div>
<div class="paragraph">
<p>First we remove the <code>poke</code> virtual functions from the domain classes:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#include &lt;string&gt;
struct Animal {
Animal(std::string name) : name(name) {}
std::string name;
virtual ~Animal() = default;
};
struct Cat : Animal {
using Animal::Animal;
};
struct Dog : Animal {
using Animal::Animal;
};
struct Bulldog : Dog {
using Dog::Dog;
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note that the Animal classes do not depend on iostreams anymore. This is a major
advantage of open-methods over virtual functions: they make it possible to
better organize dependencies.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s implement <code>poke</code>. First we need to include the library&#8217;s main header. It
defines a few macros, and injects a name - <code>virtual_ptr</code> - in the global
namespace.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#include &lt;iostream&gt;
#include &lt;boost/openmethod.hpp&gt;
using boost::openmethod::virtual_ptr;
BOOST_OPENMETHOD(
poke, // method name
(std::ostream&amp;, virtual_ptr&lt;Animal&gt;), // method signature
void); // return type</code></pre>
</div>
</div>
<div class="paragraph">
<p>This defines a free function called <code>poke</code>, which takes two arguments. The first
is the <code>ostream</code>. The second argument corresponds to the implicit <code>this</code> pointer
in a virtual function. It is now an explicit argument. Just like with virtual
functions, the exact function to execute is selected on the basis of the
argument&#8217;s <em>dynamic</em> type.</p>
</div>
<div class="paragraph">
<p>Unlike virtual functions, there is no such thing as a pure open-method that
would make a class abstract. It is not possible to determine if an overrider is
available from looking at just the current translation unit.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s add overriders for <code>Cat</code> and <code>Dog</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">BOOST_OPENMETHOD_OVERRIDE(
poke, // method name
(std::ostream &amp; os, virtual_ptr&lt;Cat&gt; cat), // overrider signature
void) { // return type
os &lt;&lt; cat-&gt;name &lt;&lt; " hisses"; // overrider body
}
BOOST_OPENMETHOD_OVERRIDE(poke, (std::ostream &amp; os, virtual_ptr&lt;Dog&gt; dog), void) {
os &lt;&lt; dog-&gt;name &lt;&lt; " barks";
}</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>Bulldog::poke</code> calls the <code>poke</code> it overrides in its <code>Dog</code> base. The equivalent
for open-methods is <code>next</code>, a function that is available only inside the body of
an overrider. It calls the next most specific overrider, i.e. what would have
been called if the overrider did not exist.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">BOOST_OPENMETHOD_OVERRIDE(
poke, (std::ostream &amp; os, virtual_ptr&lt;Bulldog&gt; dog), void) {
next(os, dog); // call base overrider
os &lt;&lt; " and bites back";
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>All classes involved in open-method calls need to be registered using the
<code>BOOST_OPENMETHOD_CLASSES</code> macro:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">BOOST_OPENMETHOD_CLASSES(Animal, Cat, Dog, Bulldog);</code></pre>
</div>
</div>
<div class="paragraph">
<p>Classes can be registered incrementally, as long as all the direct bases of a
class are listed with it in some call(s) to <code>BOOST_OPENMETHOD_CLASSES</code>. For
example, <code>Bulldog</code> can be added in a second call, as long as <code>Dog</code> is listed as
well:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">// in animals.cpp
BOOST_OPENMETHOD_CLASSES(Animal, Cat, Dog);
// in bulldog.cpp
BOOST_OPENMETHOD_CLASSES(Dog, Bulldog);</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>boost::openmethod::initialize();</code> must be called before any open-method call.
It builds the dispatch tables. Typically this is done in <code>main</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#include &lt;boost/openmethod/compiler.hpp&gt;
// only needed in the file that calls boost::openmethod::initialize()
auto main() -&gt; int {
boost::openmethod::initialize();
// ...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>We call <code>poke</code> like any ordinary function. We can pass it the animals by
reference, because <code>virtual_ptr</code> has a conversion constructor for that:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"> std::unique_ptr&lt;Animal&gt; felix(new Cat("Felix"));
std::unique_ptr&lt;Animal&gt; snoopy(new Dog("Snoopy"));
std::unique_ptr&lt;Animal&gt; hector(new Bulldog("Hector"));
poke(std::cout, *felix); // Felix hisses
std::cout &lt;&lt; ".\n";
poke(std::cout, *snoopy); // Snoopy barks
std::cout &lt;&lt; ".\n";
poke(std::cout, *hector); // Hector barks and bites
std::cout &lt;&lt; ".\n";</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="tutorials_multiple_dispatch">Multiple Dispatch</h3>
<div class="paragraph">
<p>A method can have more than one <code>virtual_ptr</code> parameter. For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">BOOST_OPENMETHOD(
encounter,
(std::ostream&amp;, virtual_ptr&lt;Animal&gt;, virtual_ptr&lt;Animal&gt;), void);
// 'encounter' catch-all implementation.
BOOST_OPENMETHOD_OVERRIDE(
encounter,
(std::ostream &amp; os, virtual_ptr&lt;Animal&gt; a, virtual_ptr&lt;Animal&gt; b), void) {
os &lt;&lt; a-&gt;name &lt;&lt; " and " &lt;&lt; b-&gt;name &lt;&lt; " ignore each other";
}
// Add definitions for specific pairs of animals.
BOOST_OPENMETHOD_OVERRIDE(
encounter,
(std::ostream &amp; os, virtual_ptr&lt;Dog&gt; /*dog1*/, virtual_ptr&lt;Dog&gt; /*dog2*/), void) {
os &lt;&lt; "Both wag tails";
}
BOOST_OPENMETHOD_OVERRIDE(
encounter, (std::ostream &amp; os, virtual_ptr&lt;Dog&gt; dog, virtual_ptr&lt;Cat&gt; cat),
void) {
os &lt;&lt; dog-&gt;name &lt;&lt; " chases " &lt;&lt; cat-&gt;name;
}
BOOST_OPENMETHOD_OVERRIDE(
encounter, (std::ostream &amp; os, virtual_ptr&lt;Cat&gt; cat, virtual_ptr&lt;Dog&gt; dog),
void) {
os &lt;&lt; cat-&gt;name &lt;&lt; " runs away from " &lt;&lt; dog-&gt;name;
}</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">// cat and dog
encounter(std::cout, *felix, *snoopy); // Felix runs away from Snoopy
std::cout &lt;&lt; ".\n";
// dog and cat
encounter(std::cout, *snoopy, *felix); // Snoopy chases Felix
std::cout &lt;&lt; ".\n";
// dog and dog
encounter(std::cout, *snoopy, *hector); // Both wag tails
std::cout &lt;&lt; ".\n";
// cat and cat
std::unique_ptr&lt;Animal&gt; tom(new Cat("Tom"));
encounter(std::cout, *felix, *tom); // Felix and Tom ignore each other
std::cout &lt;&lt; ".\n";</code></pre>
</div>
</div>
<div class="paragraph">
<p>The appropriate overrider is selected using a process similar to overload
resolution, with fallback options. If one overrider is more specialized than all
the others, call it. Otherwise, the return type is used as a tie-breaker, <em>if</em>
it is covariant with the return type of the base method. If there is still no
unique best overrider, one of the best overriders is chosen arbitrarily.</p>
</div>
</div>
<div class="sect2">
<h3 id="tutorials_headers_and_namespaces">Headers and Namespaces</h3>
<div class="paragraph">
<p>Most real-life programs will be organized in multiple files and multiple
namespaces. OpenMethod interacts with headers and namespaces naturally, if
using-directives are avoided. In that case, there are a few things to be aware
of.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s break the Animals example into headers and namespaces. First we put
<code>Animal</code> in its own header and namespace:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">// animal.hpp
#ifndef ANIMAL_HPP
#define ANIMAL_HPP
#include &lt;boost/openmethod.hpp&gt;
#include &lt;string&gt;
namespace animals {
struct Animal {
Animal(std::string name) : name(name) {
}
std::string name;
virtual ~Animal() = default;
};
BOOST_OPENMETHOD(
poke, (std::ostream&amp;, boost::openmethod::virtual_ptr&lt;Animal&gt;), void);
} // namespace animals
#endif // ANIMAL_HPP</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>BOOST_OPENMETHOD</code> can be placed in a header file. It adds several constructs to
the current namespace:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>It declares (but does not define) a <code>struct</code> named after the method.</p>
</li>
<li>
<p>It declares (but does not define) a <em>guide</em> function. It is also named after
the method, and it has the same signature (with the <code>virtual_</code> decorators
stripped). It is used to match methods and overriders. It is never defined and
it is "called" only in a non-evaluated context.</p>
</li>
<li>
<p>It defines an inline function with the same name and signature as the
method (with the <code>virtual_</code> decorators stripped).</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Next, let&#8217;s implement the <code>Cat</code> class, and a derived class, <code>Cheetah</code>, in the
<code>felines</code> namespace:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">// felines.hpp
#ifndef FELINES_HPP
#define FELINES_HPP
#include "animal.hpp"
namespace felines {
struct Cat : animals::Animal {
using Animal::Animal;
};
struct Cheetah : Cat {
using Cat::Cat;
};
} // namespace felines
#endif // FELINES_HPP</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">// cat.cpp
#include &lt;iostream&gt;
#include &lt;boost/openmethod.hpp&gt;
#include "cat.hpp"
using boost::openmethod::virtual_ptr;
namespace felines {
BOOST_OPENMETHOD_CLASSES(animals::Animal, Cat, Cheetah);
BOOST_OPENMETHOD_OVERRIDE(
poke, (std::ostream &amp; os, virtual_ptr&lt;Cat&gt; cat), void) {
os &lt;&lt; cat-&gt;name &lt;&lt; " hisses";
}
BOOST_OPENMETHOD_OVERRIDE(
poke, (std::ostream &amp; os, virtual_ptr&lt;Cheetah&gt; cat), void) {
BOOST_OPENMETHOD_OVERRIDER(
poke, (std::ostream &amp; os, virtual_ptr&lt;Cat&gt; dog), void)::fn(os, cat);
os &lt;&lt; " and runs away";
}
} // namespace felines</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>BOOST_OPENMETHOD_CLASSES</code> should be placed in an implementation file. It can
also go in a header file, but this wastes space, as the same registrar will be
created in every translation unit that includes the header. It doesn&#8217;t matter
which namespace the macro is called in. It can take be used with any class name
in scope, or with qualified names.</p>
</div>
<div class="paragraph">
<p><code>BOOST_OPENMETHOD_OVERRIDE</code> uses the guide function declared by
<code>BOOST_OPENMETHOD</code> to locate a method that can be called with the same arguments
as the overrider itself. It "calls" the guide function in a non-evaluated
context, passing it a <code>std::ostream&amp;</code> and a <code>virtual_ptr&lt;Cat&gt;</code>. The return type
of the guide function is the method to add the overrider to. Exactly one guide
function must match. The normal rules of overload resolution apply. In that
case, the guide function is found via argument dependant lookup (ADL).</p>
</div>
<div class="paragraph">
<p>The macro adds several constructs to the current namespace:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>It declares (but does not define) a <code>struct</code> template with one type parameter,
named after the method. The template acts like a container for overriders.</p>
</li>
<li>
<p>It specializes the template for the signature of the overrider. Inside the
struct, it defines the <code>next</code> and <code>has_next</code> members, and a static function
called <code>fn</code>. The block following the macro is the body of the <code>fn</code> function.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>It follows that <code>BOOST_OPENMETHOD_OVERRIDE</code> should be placed in an
implementation file. <code>BOOST_OPENMETHOD_INLINE_OVERRIDE</code> works like
<code>BOOST_OPENMETHOD_OVERRIDE</code>, but it defines the <code>fn</code> function as inline, so it
can be used in a header file.</p>
</div>
<div class="paragraph">
<p>The overrider for Cats can be accessed in the same translation unit, after it
has been defined, using the <code>BOOST_OPENMETHOD_OVERRIDER</code> macro. It expands to
the specialization of the overrider container for the overrider&#8217;s signature. We
call the static <code>fn</code> function to call the overrider.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
The Cheetah overrider calls the specific overrider for <code>Cat</code>, for
illustration purpose. It is usually better to call <code>next</code> instead.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Let&#8217;s implement the <code>Dog</code> class, in the <code>canines</code> namespace. This time we want
the overrider to be accessible in other translation units. We can declare an
overrider with <code>BOOST_OPENMETHOD_DECLARE_OVERRIDER</code>, without actually defining
the static function <code>fn</code> just yet.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#ifndef CANINES_HPP
#define CANINES_HPP
#include &lt;iosfwd&gt;
#include &lt;boost/openmethod.hpp&gt;
#include "animal.hpp"
namespace canines {
struct Dog : animals::Animal {
using Animal::Animal;
};
BOOST_OPENMETHOD_DECLARE_OVERRIDER(
poke, (std::ostream &amp; os, boost::openmethod::virtual_ptr&lt;Dog&gt; dog), void);
} // namespace canines
#endif // CANINES_HPP</code></pre>
</div>
</div>
<div class="paragraph">
<p>Unlike function declarations, which can occur multiple times in a TU, an
overrider declaration cannot. For example, this is illegal:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">BOOST_OPENMETHOD_DECLARE_OVERRIDER(
poke, (std::ostream&amp;, virtual_ptr&lt;Dog&gt;), void);
BOOST_OPENMETHOD_DECLARE_OVERRIDER(
poke, (std::ostream&amp;, virtual_ptr&lt;Dog&gt;), void);</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now we use <code>BOOST_OPENMETHOD_DEFINE_OVERRIDER</code> to define the overrider:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#include &lt;iostream&gt;
#include &lt;boost/openmethod.hpp&gt;
#include "dog.hpp"
namespace canines {
BOOST_OPENMETHOD_CLASSES(animals::Animal, Dog);
BOOST_OPENMETHOD_DEFINE_OVERRIDER(
poke, (std::ostream &amp; os, boost::openmethod::virtual_ptr&lt;Dog&gt; dog), void) {
os &lt;&lt; dog-&gt;name &lt;&lt; " barks";
}
} // namespace canines</code></pre>
</div>
</div>
<div class="paragraph">
<p>Let&#8217;s look at the main program now. It derived <code>Bulldog</code> from <code>Dog</code> and provides
an overrider for the new class:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#include &lt;iostream&gt;
#include &lt;boost/openmethod.hpp&gt;
#include &lt;boost/openmethod/compiler.hpp&gt;
#include "animal.hpp"
#include "cat.hpp"
#include "dog.hpp"
using boost::openmethod::virtual_ptr;
struct Bulldog : canines::Dog {
using Dog::Dog;
};
BOOST_OPENMETHOD_CLASSES(canines::Dog, Bulldog);
BOOST_OPENMETHOD_OVERRIDE(
poke, (std::ostream &amp; os, virtual_ptr&lt;Bulldog&gt; dog), void) {
canines::BOOST_OPENMETHOD_OVERRIDER(
poke, (std::ostream &amp; os, virtual_ptr&lt;canines::Dog&gt; dog),
void)::fn(os, dog);
os &lt;&lt; " and bites back";
}
auto main() -&gt; int {
boost::openmethod::initialize();
std::unique_ptr&lt;animals::Animal&gt; felix(new felines::Cat("Felix"));
std::unique_ptr&lt;animals::Animal&gt; azaad(new felines::Cheetah("Azaad"));
std::unique_ptr&lt;animals::Animal&gt; snoopy(new canines::Dog("Snoopy"));
std::unique_ptr&lt;animals::Animal&gt; hector(new Bulldog("Hector"));
poke(std::cout, *felix); // Felix hisses
std::cout &lt;&lt; ".\n";
poke(std::cout, *azaad); // Azaad hisses and runs away
std::cout &lt;&lt; ".\n";
poke(std::cout, *snoopy); // Snoopy barks
std::cout &lt;&lt; ".\n";
poke(std::cout, *hector); // Hector barks and bites
std::cout &lt;&lt; ".\n";
return 0;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Again ADL plays a role: it helps the overrider (and <code>main</code>) to locate the <code>poke</code>
method.</p>
</div>
<div class="paragraph">
<p>This example is the "happy scenario", where namespaces are used conservatively.</p>
</div>
<div class="paragraph">
<p>The <code>OVERRIDE</code> macros don&#8217;t interact well with <code>using</code> directives. For example
this code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">using namespace animals;
using namespace canines;
using namespace felines;
struct Bulldog : Dog {
using Dog::Dog;
};
BOOST_OPENMETHOD_CLASSES(Dog, Bulldog);
BOOST_OPENMETHOD_OVERRIDE(
poke, (std::ostream &amp; os, virtual_ptr&lt;Bulldog&gt; dog), void) {
next(os, dog);
os &lt;&lt; " and bites back";
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>&#8230;&#8203;will fail to compile, with an error like "reference to
'poke_boost_openmethod_overriders' is ambiguous". That is because the overrider
containers exist in both the canines and felines namespaces, with the same name.</p>
</div>
<div class="paragraph">
<p>Finally, the names passed as first arguments to the BOOST_OPENMETHOD and
BOOST_OPENMETHOD_OVERRIDE macros must be identifiers. Qualified names are not
allowed. Consider:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">using animals::Animal;
namespace app_specific_behavior {
BOOST_OPENMETHOD(
meet, (std::ostream&amp;, virtual_ptr&lt;Animal&gt;, virtual_ptr&lt;Animal&gt;), void);
} // namespace app_specific_behavior
BOOST_OPENMETHOD_OVERRIDE(
meet, (std::ostream&amp; os, virtual_ptr&lt;Animal&gt;, virtual_ptr&lt;Animal&gt;), void) {
os &lt;&lt; "ignore";
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Here, the guide function cannot be found, even via ADL. We get an error like
"use of undeclared identifier 'meet_boost_openmethod_guide'". How do we solve
this? We might be tempted to use a qualified name:
<code>app_specific_behavior::meet</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">BOOST_OPENMETHOD_OVERRIDE(
app_specific_behavior::meet,
(std::ostream&amp; os, virtual_ptr&lt;Animal&gt;, virtual_ptr&lt;Animal&gt;), void) {
os &lt;&lt; "ignore";
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>But <code>BOOST_OPENMETHOD_OVERRIDE</code> also uses the name to derive the overrider
container&#8217;s name, using preprocessor token pasting, resulting in an invalid
declaration error.</p>
</div>
<div class="paragraph">
<p>We need to do is to make <code>BOOST_OPENMETHOD_OVERRIDE</code> "see" the guide function.
Its name is returned by macro <code>BOOST_OPENMETHOD_GUIDE(NAME)</code>. We can use a
using-declaration to bring the guide function into the current scope:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">using app_specific_behavior::BOOST_OPENMETHOD_GUIDE(meet);
BOOST_OPENMETHOD_OVERRIDE(
meet, (std::ostream&amp; os, virtual_ptr&lt;Animal&gt;, virtual_ptr&lt;Animal&gt;), void) {
os &lt;&lt; "ignore";
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="tutorials_friendship">Friendship</h3>
<div class="paragraph">
<p>We can use overrider containers to grant friendship to a specific overrider, or
to all the overriders of a method. The name of the container template is
returned by <code>BOOST_OPENMETHOD_OVERRIDERS</code>. The template argument for a
specialization is the signature of the overrider. For example, the overrider of
<code>poke</code> for <code>Cat</code> is:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">BOOST_OPENMETHOD_OVERRIDERS(poke)&lt;
void(std::ostream&amp; os, virtual_ptr&lt;Cat&gt; cat)&gt;::fn;</code></pre>
</div>
</div>
<div class="paragraph">
<p>We can thus grant friendship to all the overriders of <code>poke</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">class Cat;
class Dog;
class Animal {
// ...
private:
std::string name;
template&lt;typename&gt; friend struct BOOST_OPENMETHOD_OVERRIDERS(poke);
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>Be aware, though, that the overriders of <em>any</em> method called <code>poke</code> - with any
signature - are granted friendship.</p>
</div>
<div class="paragraph">
<p>We can also befriend individual overriders:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">class Cat;
class Dog;
template&lt;typename&gt; struct BOOST_OPENMETHOD_OVERRIDERS(poke);
class Animal {
// ...
private:
std::string name;
friend struct BOOST_OPENMETHOD_OVERRIDERS(poke)&lt;void(std::ostream&amp;, virtual_ptr&lt;Cat&gt;)&gt;;
friend struct BOOST_OPENMETHOD_OVERRIDERS(poke)&lt;void(std::ostream&amp;, virtual_ptr&lt;Dog&gt;)&gt;;
};</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="tutorials_performance">Performance</h3>
<div class="paragraph">
<p>Open-methods are almost as fast as ordinary virtual member functions when
compiled with optimization.</p>
</div>
<div class="paragraph">
<p>clang compiles the following code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">void call_poke_via_ref(std::ostream&amp; os, Animal&amp; a) {
poke(os, a);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>&#8230;&#8203;to this on the x64 architecture (variable names have been shortened for
readability):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="asm">mov rax, qword ptr [rsi]
mov rdx, qword ptr [rip + mult]
imul rdx, qword ptr [rax - 8]
movzx ecx, byte ptr [rip + shift]
shr rdx, cl
mov rax, qword ptr [rip + vptrs]
mov rax, qword ptr [rax + 8*rdx]
mov rcx, qword ptr [rip + poke::slots_strides]
mov rax, qword ptr [rax + 8*rcx]
jmp rax</code></pre>
</div>
</div>
<div class="paragraph">
<p>llvm-mca estimates a throughput of 4 cycles per dispatch. Comparatively, calling
a native virtual functions takes one cycle. However, the difference is amortized
by the time spent passing the arguments and returning from the function; plus,
of course, executing the body of the function.</p>
</div>
<div class="paragraph">
<p>Micro benchmarks suggest that dispatching an open-methods with a single virtual
argument is between 30% and 50% slower than calling the equivalent virtual
function, with an empty body and no other arguments.</p>
</div>
<div class="paragraph">
<p>However, <code>call_poke</code> does two things: it constructs a <code>virtual_ptr&lt;Animal&gt;</code> from
an <code>Animal&amp;</code>; and then it calls the method. The construction of the
<code>virtual_ptr</code> is the costly part, as it involves a hash table lookup. Once that
price has been paid, the <code>virtual_ptr</code> can be used multiple times. It is passed
to the overrider, which can make further method calls through it. It can be
stored in variables in place of plain pointers.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s look at another example: an AST for an arithmetic calculator:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#include &lt;iostream&gt;
#include &lt;boost/openmethod.hpp&gt;
#include &lt;boost/openmethod/compiler.hpp&gt;
using boost::openmethod::virtual_ptr;
struct Node {
virtual ~Node() {}
};
struct Literal : Node {
explicit Literal(int value) : value(value) {}
int value;
};
struct Plus : Node {
Plus(virtual_ptr&lt;Node&gt; left, virtual_ptr&lt;Node&gt; right)
: left(left), right(right) {}
virtual_ptr&lt;Node&gt; left, right;
};
struct Negate : Node {
explicit Negate(virtual_ptr&lt;Node&gt; node) : child(node) {}
virtual_ptr&lt;Node&gt; child;
};
BOOST_OPENMETHOD(value, (virtual_ptr&lt;Node&gt;), int);
BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr&lt;Literal&gt; node), int) {
return node-&gt;value;
}
BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr&lt;Plus&gt; node), int) {
return value(node-&gt;left) + value(node-&gt;right);
}
BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr&lt;Negate&gt; node), int) {
return -value(node-&gt;child);
}
BOOST_OPENMETHOD_CLASSES(Node, Literal, Plus, Negate);
auto main() -&gt; int {
boost::openmethod::initialize();
Literal one(1), two(2);
Plus sum(one, two);
Negate neg(sum);
std::cout &lt;&lt; value(neg) &lt;&lt; "\n"; // -3
return 0;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>Negate</code> overrider compiles to:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="asm">mov rdi, qword ptr [rsi + 8]
mov rsi, qword ptr [rsi + 16]
mov rax, qword ptr [rip + value::slots_strides]
call qword ptr [rdi + 8*rax]
neg eax
pop rcx</code></pre>
</div>
</div>
<div class="paragraph">
<p>The first two instructions read the <code>virtual_ptr</code> from <code>this</code> - placing its
content in registers <code>rdi</code> and <code>rsi</code>.</p>
</div>
<div class="paragraph">
<p>The next two instructions are the method call proper. According to llvm-mca,
they take one cycle - the same as a native virtual function call.</p>
</div>
<div class="paragraph">
<p>When we create the <code>Plus</code> and <code>Negate</code> nodes, we call the conversion
constructors of <code>virtual_ptr&lt;Node&gt;</code>, which occur the cost of hash table lookups.
However, in this example, we know the exact types of the objects. In that case,
we can use <code>final_virtual_ptr</code> to construct the <code>virtual_ptr</code> using a single
instruction. For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">Literal one(1);
Negate neg(boost::openmethod::final_virtual_ptr(one));</code></pre>
</div>
</div>
<div class="paragraph">
<p>&#8230;&#8203;compiles to:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="asm">;; construct Literal
lea rax, [rip + vtable for Literal+16]
mov qword ptr [rsp], rax
mov dword ptr [rsp+8], 1
;; construct Negate
mov rax, qword ptr [rip+static_vptr&lt;Literal&gt;] ; address of openmethod v-table
lea rcx, [rip+vtable for Negate+16] ; address of native v-table
mov qword ptr [rsp+16], rcx ; set native v-table
mov qword ptr [rsp+24], rax ; set openmethod v-table
mov rax, rsp ; address of 'one'
mov qword ptr [rsp+32], rax ; set vptr object pointer to 'one'</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>final_virtual_ptr</code> does not require its argument to have a polymorphic type.</p>
</div>
</div>
<div class="sect2">
<h3 id="tutorials_smart_pointers">Smart Pointers</h3>
<div class="paragraph">
<p><code>virtual_ptr</code> can also be used in combination with smart pointers.
<code>virtual_ptr&lt;std::shared_ptr&lt;Class&gt;&gt;</code> (aliased to <code>shared_virtual_ptr&lt;Class&gt;</code>)
and <code>virtual_ptr&lt;std::unique_ptr&lt;Class&gt;&gt;</code> (aliased to
<code>unique_virtual_ptr&lt;Class&gt;</code>) deliver the convenience of automatic memory
management with the speed of <code>virtual_ptr</code>. Convenience functions
<code>make_shared_virtual</code> and <code>make_unique_virtual</code> create an object and return a
smart virtual_ptr to it. Since the exact type of the object is known, the vptr
is read from a static variable, without incuring the cost of a hash table
lookup.</p>
</div>
<div class="paragraph">
<p>Here is a variaton of the AST example that uses dynamic allocation and unique
pointers:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#include &lt;iostream&gt;
#include &lt;memory&gt;
#include &lt;boost/openmethod.hpp&gt;
#include &lt;boost/openmethod/interop/std_unique_ptr.hpp&gt;
#include &lt;boost/openmethod/compiler.hpp&gt;
using namespace boost::openmethod::aliases;
struct Node {
virtual ~Node() {}
};
struct Literal : Node {
Literal(int value) : value(value) {}
int value;
};
struct Plus : Node {
Plus(unique_virtual_ptr&lt;Node&gt; left, unique_virtual_ptr&lt;Node&gt; right)
: left(std::move(left)), right(std::move(right)) {}
unique_virtual_ptr&lt;Node&gt; left, right;
};
struct Negate : Node {
Negate(unique_virtual_ptr&lt;Node&gt; node) : child(std::move(node)) {}
unique_virtual_ptr&lt;Node&gt; child;
};
BOOST_OPENMETHOD(value, (virtual_ptr&lt;Node&gt;), int);
BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr&lt;Literal&gt; node), int) {
return node-&gt;value;
}
BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr&lt;Plus&gt; node), int) {
return value(node-&gt;left) + value(node-&gt;right);
}
BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr&lt;Negate&gt; node), int) {
return -value(node-&gt;child);
}
BOOST_OPENMETHOD_CLASSES(Node, Literal, Plus, Negate);
auto main() -&gt; int {
boost::openmethod::initialize();
auto expr = make_unique_virtual&lt;Negate&gt;(
make_unique_virtual&lt;Plus&gt;(
make_unique_virtual&lt;Literal&gt;(1),
make_unique_virtual&lt;Literal&gt;(2)));
std::cout &lt;&lt; value(expr) &lt;&lt; "\n"; // -3
return 0;
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="tutorials_alternatives_to_virtual_ptr">Alternatives to virtual_ptr</h3>
<div class="paragraph">
<p>Virtual arguments can be passed as plain references. In a method declaration,
parameters with a type decorated with <code>virtual_</code> are considered in overrider
selection (along with <code>virtual_ptr</code> parameters).</p>
</div>
<div class="paragraph">
<p>For example, the <code>poke</code> open-method in the Animals example can be rewritten as:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">struct Animal {
virtual ~Animal() = default;
};
struct Cat : Animal {};
using boost::openmethod::virtual_;
BOOST_OPENMETHOD(poke, (std::ostream&amp;, virtual_&lt;Animal&amp;&gt;), void);
BOOST_OPENMETHOD_OVERRIDE(poke, (std::ostream &amp; os, Cat&amp; /*cat*/), void) {
os &lt;&lt; "hiss";
}
BOOST_OPENMETHOD_CLASSES(Animal, Cat);
int main() {
boost::openmethod::initialize();
Cat cat;
poke(std::cout, cat); // hiss
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note that <code>virtual_</code> is not used in the overrider. It is also removed from the
method&#8217;s signature.</p>
</div>
<div class="paragraph">
<p>By itself, <code>virtual_</code> does not provide any benefits. Passing the virtual
argument by reference almost compiles to the same code as creating a
<code>virtual_ptr</code>, using it for one call, then throwing it way. The only difference
is that the virtual argument is passed as one pointer instead of two.</p>
</div>
<div class="paragraph">
<p>However, we can now customize how the vptr is obtained. When the method sees a
<code>virtual_</code> parameter, it looks for a <code>boost_openmethod_vptr</code> function that takes
the parameter (by const reference), and returns a <code>vptr_type</code>. If one is found,
it is called to obtain the vptr. The vptr for a specific registered class can be
obtained via a variable template <code>static_vptr</code>, nested in class <code>default_registry</code>
(more on policies below).</p>
</div>
<div class="paragraph">
<p>In the following example, we embed a vptr in the object, just like the vptr for
native virtual functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">class Animal {
protected:
boost::openmethod::vptr_type vptr;
friend auto boost_openmethod_vptr(const Animal&amp; a, void*) {
return a.vptr;
}
public:
Animal() {
vptr = boost::openmethod::default_registry::static_vptr&lt;Animal&gt;;
}
};
class Cat : public Animal {
public:
Cat() {
vptr = boost::openmethod::default_registry::static_vptr&lt;Cat&gt;;
}
};
BOOST_OPENMETHOD(poke, (std::ostream&amp;, virtual_&lt;Animal&amp;&gt;), void);
BOOST_OPENMETHOD_OVERRIDE(poke, (std::ostream &amp; os, Cat&amp; /*cat*/), void) {
os &lt;&lt; "hiss\n";
}
BOOST_OPENMETHOD_CLASSES(Animal, Cat);
int main() {
boost::openmethod::initialize();
Cat cat;
poke(std::cout, cat); // hiss
}</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
With this approach, classes need not be polymorphic. A virtual
destructor might be needed for correct destruction of objects, but it is not
required by the library.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The <code>inplace_vptr</code> CRTP class automates the creation and management of embedded
vptrs.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#include &lt;boost/openmethod/inplace_vptr.hpp&gt;
class Animal : public boost::openmethod::inplace_vptr&lt;Animal&gt; {
};
class Cat : public Animal, public boost::openmethod::inplace_vptr&lt;Cat, Animal&gt; {
};
BOOST_OPENMETHOD(poke, (std::ostream&amp;, virtual_&lt;Animal&amp;&gt;), void);
BOOST_OPENMETHOD_OVERRIDE(poke, (std::ostream &amp; os, Cat&amp; /*cat*/), void) {
os &lt;&lt; "hiss\n";
}
int main() {
boost::openmethod::initialize();
Cat cat;
poke(std::cout, cat); // hiss
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>If <code>inplace_vptr</code> is passed only the class being defined, it adds a vptr to it, and
defines a <code>boost_openmethod_vptr</code> friend function. If more classes are passed,
they must be the direct bases of the class potentially involved in open-method
calls. Its constructor and destructor set the vptr to point to the v-table for
the class. <code>inplace_vptr</code> also takes care of registering the classes, so this time
the call to <code>BOOST_OPENMETHOD_CLASSES</code> is not needed.</p>
</div>
</div>
<div class="sect2">
<h3 id="tutorials_core_api">Core API</h3>
<div class="paragraph">
<p>OpenMethod provides a macro-free interface: the core API. This is useful in
certain situations, for example when combining open-methods and templates.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s rewrite the Animals example using the core API. An open-method is
implemented as an instance of the <code>method</code> template. Its parameters are a
function signature and a return type:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#include &lt;boost/openmethod/core.hpp&gt;
using namespace boost::openmethod;
class poke_openmethod;
using poke = method&lt;
poke_openmethod(std::ostream&amp;, virtual_&lt;Animal&amp;&gt;), void&gt;;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>poke_openmethod</code> class acts as the method&#8217;s identifier: it separates it
from other methods with the same signature. The exact name does not really
matter, and the class needs not be defined, only declared. Inventing a class
name can get tedious, so OpenMethod provides a macro for that:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#include &lt;boost/openmethod/macros.hpp&gt;
class BOOST_OPENMETHOD_ID(poke);
using poke = method&lt;
BOOST_OPENMETHOD_ID(poke),
auto(std::ostream&amp;, virtual_ptr&lt;Animal&gt;)-&gt;void&gt;;</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
BOOST_OPENMETHOD and associated macros use <code>BOOST_OPENMETHOD_ID</code> in
their implementation. This makes it possible to mix the "macro" and "core"
styles.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>We call the method via the nested function object <code>fn</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">poke::fn(std::cout, animal);</code></pre>
</div>
</div>
<div class="paragraph">
<p>Overriders are ordinary functions, added to a method using the nested template
<code>override</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">auto poke_cat(std::ostream&amp; os, virtual_ptr&lt;Cat&gt; /*cat*/) {
os &lt;&lt; "hiss";
}
static poke::override&lt;poke_cat&gt; override_poke_cat;</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<code>override</code> can register multiple overriders.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>In C++26, we will be able to use <code>_</code> instead of inventing a one-time-use
identifier. In the meantime, OpenMethod provides a small convenience macro:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#include &lt;boost/openmethod/macros.hpp&gt;
auto poke_dog(std::ostream&amp; os, virtual_ptr&lt;Dog&gt; /*dog*/) {
os &lt;&lt; "bark";
}
BOOST_OPENMETHOD_REGISTER(poke::override&lt;poke_dog&gt;);</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>next</code> is available from the method&#8217;s nested <code>next</code> template:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">auto poke_bulldog(std::ostream&amp; os, virtual_ptr&lt;Bulldog&gt; dog) -&gt; void {
poke::next&lt;poke_bulldog&gt;(os, dog);
os &lt;&lt; " and bite";
}
BOOST_OPENMETHOD_REGISTER(poke::override&lt;poke_bulldog&gt;);</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
Since the function uses itself as a template argument in its body, its
return type cannot be deduced. It must be specified explicitly, either by using
the old function declaration style or a trailing return type.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Why not call <code>poke_dog</code> directly? We could; however, keep in mind that, in a
real program, a translation unit is not necessarily aware of the overriders
added elsewhere - especially in presence of dynamic loading.</p>
</div>
<div class="paragraph">
<p>We register the classes with <code>use_classes</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">BOOST_OPENMETHOD_REGISTER(use_classes&lt;Animal, Cat, Dog, Bulldog&gt;);</code></pre>
</div>
</div>
<div class="paragraph">
<p>Finally, we call the method via the static member of the method class <code>fn</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">auto main() -&gt; int {
boost::openmethod::initialize();
std::unique_ptr&lt;Animal&gt; a(new Cat);
std::unique_ptr&lt;Animal&gt; b(new Dog);
std::unique_ptr&lt;Animal&gt; c(new Bulldog);
poke::fn(std::cout, *a); // prints "hiss"
std::cout &lt;&lt; "\n";
poke::fn(std::cout, *b); // prints "bark"
std::cout &lt;&lt; "\n";
poke::fn(std::cout, *c); // prints "bark and bite"
std::cout &lt;&lt; "\n";
return 0;</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="tutorials_policies_and_policys">Policies and Facets</h3>
<div class="paragraph">
<p>Methods and classes are scoped in a policy. A method can only reference classes
registered in the same policy. If a class is used as a virtual parameter in
methods using different policies, it must be registered with each of them.</p>
</div>
<div class="paragraph">
<p>Class templates <code>use_classes</code>, <code>method</code>, <code>virtual_ptr</code>, and macros
<code>BOOST_OPENMETHOD</code> and <code>BOOST_OPENMETHOD_CLASSES</code>, accept an additional
argument, a policy class, which defaults to <code>policies::debug</code> in debug builds,
and <code>policies::release</code> in release builds.</p>
</div>
<div class="paragraph">
<p>A policy has a collection of <em>policys</em>. Each policy belongs to a policy category. A
policy may contain at most one policy of a given category. Facets control how
type information is obtained, how vptrs are fetched, how errors are handled and
printed, etc. Some are used in <code>initialize</code> and method dispatch; some are used
by other policys in the same policy as part of their implementation. See the
reference for the list of policys. Policies and policys are placed in the
<code>boost::openmethod::policies</code> namespace. Two stock policies are provided by the
library: <code>release</code> and <code>debug</code>.</p>
</div>
<div class="paragraph">
<p>The <code>release</code> policy contains the following policys:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">policy category</th>
<th class="tableblock halign-left valign-top">policy</th>
<th class="tableblock halign-left valign-top">role</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">rtti</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">std_rtti</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">provides type information for classes and objects</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">extern_vptr</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">vptr_vector</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">stores vptrs in an indexed collection</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">type_hash</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">fast_perfect_hash</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">hash type id to an index in a vector</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">error_handler</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">default_error_handler</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">handles errors</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>The <code>debug</code> policy contains the same policys as <code>release</code>, plus a few more:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">policy category</th>
<th class="tableblock halign-left valign-top">policy</th>
<th class="tableblock halign-left valign-top">role</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">runtime_checks</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">(itself)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">enables runtime checks</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">output</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">basic_error_output</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">prints error descriptions to <code>stderr</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">trace</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">basic_trace_output</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">enables <code>initialize</code> to print information about dispatch table construction to <code>stderr</code></p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>Policies, and some policys, have static variables. When it is the case, they are
implemented as CRTP classes.</p>
</div>
<div class="paragraph">
<p>Policies can be created from scratch, using the <code>basic_policy</code> template, or
constructed from existing policies by adding and removing policys. For example,
<code>policies::debug</code> is a tweak of <code>policies::release</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod::policies {
struct debug : release::fork&lt;debug&gt;::with&lt;
runtime_checks, basic_error_output&lt;debug&gt;,
basic_trace_output&lt;debug&gt;&gt; {};
}</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>boost::openmethod::default_registry</code> is an alias to <code>release</code> or <code>debug</code>,
depending on the value of preprocessor symbols <code>NDEBUG</code>. The default policy can
be overriden by defining the macroprocessor symbol
<code>BOOST_OPENMETHOD_DEFAULT_REGISTRY</code> <em>before</em> including
<code>&lt;boost/openmethod/core.hpp&gt;</code>. The value of the symbol is used as a default
template parameter for <code>use_classes</code>, <code>method</code>, <code>virtual_ptr</code>, and others. Once
the <code>core</code> header has been included, changing <code>BOOST_OPENMETHOD_DEFAULT_REGISTRY</code>
has no effect.</p>
</div>
</div>
<div class="sect2">
<h3 id="tutorials_error_handling">Error Handling</h3>
<div class="paragraph">
<p>When an error is encountered, the program is terminated by a call to <code>abort</code>. If
the policy contains an <code>error_handler</code> policy, it provides an <code>error</code> member
function (or overloaded functions) to be called with an object identifying the
error. The <code>release</code> and <code>debug</code> policies implement the error policy with
<code>default_error_handler</code>, which wraps the error object in a variant, and calls a
handler via a <code>std::function</code>. By default, it prints a description of the error
to <code>stderr</code> in the <code>debug</code> policy, and does nothing in the <code>release</code> policy. The
handler can be set with <code>set_error_handler</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#include &lt;iostream&gt;
#include &lt;variant&gt;
#include &lt;boost/openmethod.hpp&gt;
#include &lt;boost/openmethod/compiler.hpp&gt;
using boost::openmethod::virtual_ptr;
struct Animal {
virtual ~Animal() = default;
};
struct Cat : Animal {};
struct Dog : Animal {};
BOOST_OPENMETHOD_CLASSES(Animal, Cat, Dog);
BOOST_OPENMETHOD(trick, (std::ostream&amp;, virtual_ptr&lt;Animal&gt;), void);
BOOST_OPENMETHOD_OVERRIDE(
trick, (std::ostream &amp; os, virtual_ptr&lt;Dog&gt; /*dog*/), void) {
os &lt;&lt; "spin\n";
}
auto main() -&gt; int {
namespace bom = boost::openmethod;
bom::initialize();
bom::default_registry::error_handler::set([](const auto&amp; error) {
if (std::holds_alternative&lt;bom::not_implemented_error&gt;(error)) {
throw std::runtime_error("not implemented");
}
});
Cat felix;
Dog hector, snoopy;
std::vector&lt;Animal*&gt; animals = {&amp;hector, &amp;felix, &amp;snoopy};
for (auto animal : animals) {
try {
trick(std::cout, *animal);
} catch (std::runtime_error&amp; error) {
std::cerr &lt;&lt; error.what() &lt;&lt; "\n";
}
}
return 0;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Output:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="console">spin
not implemented
spin</code></pre>
</div>
</div>
<div class="paragraph">
<p>We can also replace the <code>error_handler</code> policy with our own. For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#include &lt;iostream&gt;
#include &lt;boost/openmethod/default_registry.hpp&gt;
struct Animal {
virtual ~Animal() = default;
};
struct Cat : Animal {};
struct Dog : Animal {};
namespace bom = boost::openmethod;
struct throw_if_not_implemented : bom::policies::error_handler {
template&lt;class Registry&gt;
struct fn {
static auto error(const bom::openmethod_error&amp;) -&gt; void {
}
static auto error(const bom::not_implemented_error&amp; err) -&gt; void {
throw err;
}
};
};
struct custom_registry : bom::default_registry::with&lt;throw_if_not_implemented&gt; {
};
#define BOOST_OPENMETHOD_DEFAULT_REGISTRY custom_registry
#include &lt;boost/openmethod.hpp&gt;
#include &lt;boost/openmethod/compiler.hpp&gt;
using boost::openmethod::virtual_ptr;
BOOST_OPENMETHOD_CLASSES(Animal, Cat, Dog);
BOOST_OPENMETHOD(trick, (std::ostream&amp;, virtual_ptr&lt;Animal&gt;), void);
BOOST_OPENMETHOD_OVERRIDE(
trick, (std::ostream &amp; os, virtual_ptr&lt;Dog&gt; /*dog*/), void) {
os &lt;&lt; "spin\n";
}
auto main() -&gt; int {
bom::initialize();
Cat felix;
Dog hector, snoopy;
std::vector&lt;Animal*&gt; animals = {&amp;hector, &amp;felix, &amp;snoopy};
for (auto animal : animals) {
try {
trick(std::cout, *animal);
} catch (bom::not_implemented_error&amp;) {
std::cout &lt;&lt; "not implemented\n";
}
}
return 0;
}</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="console">spin
not implemented
spin</code></pre>
</div>
</div>
<div class="paragraph">
<p>Stock policy <code>throw_error_handler</code> does this for all the exception types:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod::policies {
struct throw_error_handler : error_handler {
template&lt;class Error&gt;
[[noreturn]] static auto error(const Error&amp; error) -&gt; void {
throw error;
}
};
} // namespace boost::openmethod::policies</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="tutorials_custom_rtti">Custom RTTI</h3>
<div class="paragraph">
<p>Stock policies use the <code>std_rtti</code> implementation of <code>rtti</code>. Here is its full
source:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">struct std_rtti : rtti {
template&lt;class Class&gt;
static constexpr auto is_polymorphic = std::is_polymorphic_v&lt;Class&gt;;
template&lt;typename T&gt;
static type_id static_type() {
return reinterpret_cast&lt;type_id&gt;(&amp;typeid(T));
}
template&lt;typename T&gt;
static type_id dynamic_type(const T&amp; obj) {
return reinterpret_cast&lt;type_id&gt;(&amp;typeid(obj));
}
template&lt;class Stream&gt;
static void type_name(type_id type, Stream&amp; stream) {
stream &lt;&lt; reinterpret_cast&lt;const std::type_info*&gt;(type)-&gt;name();
}
static std::type_index type_index(type_id type) {
return std::type_index(*reinterpret_cast&lt;const std::type_info*&gt;(type));
}
template&lt;typename D, typename B&gt;
static D dynamic_cast_ref(B&amp;&amp; obj) {
return dynamic_cast&lt;D&gt;(obj);
}
};</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p><code>is_polymorphic</code> is used to check if a class is polymorphic. This template is
required.</p>
</li>
<li>
<p><code>static_type</code> is used by class registration, by <code>virtual_ptr</code>'s "final"
constructs, and to format error and trace messages. <code>T</code> is not restricted to
the classes that appear as virtual parameters. This function is required.</p>
</li>
<li>
<p><code>dynamic_type</code> is used to locate the v-table for an object. This function is
usually required. If only the <code>virtual_ptr</code> "final" constructs are used, or
if <code>boost_openmethod_vptr</code> is provided for all the classes in the policy, it
can be omitted.</p>
</li>
<li>
<p><code>type_name</code> writes a representation of <code>type</code> to <code>stream</code>. It is used to format
error and trace messages. <code>Stream</code> is a lighweight version of <code>std::ostream</code>
with reduced functionality. It only supports insertion of <code>const char*</code>,
<code>std::string_view</code>, pointers and <code>std::size_t</code>. This function is optional;
if it is not provided, "type_id(<em>type</em>)" is used.</p>
</li>
<li>
<p><code>type_index</code> returns an object that <em>uniquely</em> identifies a class. Some forms
of RTTI (most notably, C++'s <code>typeid</code> operator) do not guarantee that the
type information object for a class is unique within the same program. This
function is optional; if not provided, <code>type</code> is assumed to be unique, and
used as is.</p>
</li>
<li>
<p><code>dynamic_cast_ref</code> casts <code>obj</code> to class <code>D</code>. <code>B&amp;&amp;</code> is either a lvalue reference
(possibly cv-qualified) or a rvalue reference. <code>D</code> has the same reference
category (and cv-qualifier if applicable) as <code>B</code>. This function is required
only in presence of virtual inheritance.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Consider a custom RTTI implementation:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">struct Animal {
Animal(unsigned type) : type(type) {
}
virtual ~Animal() = default;
unsigned type;
static constexpr unsigned static_type = 1;
};
struct Cat : Animal {
Cat() : Animal(static_type) {
}
static constexpr unsigned static_type = 2;
};
// ditto for Dog</code></pre>
</div>
</div>
<div class="paragraph">
<p>This scheme has an interesting property: its type ids are monotonically
allocated in a small, dense range. Thus, we don&#8217;t need to hash them. We can use
them as indexes in the table of vptrs.</p>
</div>
<div class="paragraph">
<p>This time we are going to replace the default policy globally. First we need to
define the custom RTTI policy. We must <em>not</em> include
<code>&lt;boost/openmethod/core.hpp&gt;</code> or any header that includes it yet.</p>
</div>
<div class="paragraph">
<p>Here is the policy implementation:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace bom = boost::openmethod;
struct custom_rtti : bom::policies::rtti {
template&lt;class Registry&gt;
struct fn : bom::policies::rtti::fn&lt;Registry&gt; {
template&lt;class T&gt;
static constexpr bool is_polymorphic = std::is_base_of_v&lt;Animal, T&gt;;
template&lt;typename T&gt;
static auto static_type() -&gt; bom::type_id {
if constexpr (is_polymorphic&lt;T&gt;) {
return reinterpret_cast&lt;bom::type_id&gt;(T::static_type);
} else {
return nullptr;
}
}
template&lt;typename T&gt;
static auto dynamic_type(const T&amp; obj) -&gt; bom::type_id {
if constexpr (is_polymorphic&lt;T&gt;) {
return reinterpret_cast&lt;bom::type_id&gt;(obj.type);
} else {
return nullptr;
}
}
};
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>This policy is quite minimal. It does not support virtual inheritance. It would
not produce good error or trace messages, because types would be represented by
their integer ids.</p>
</div>
<div class="paragraph">
<p>This time we create a policy from scratch. For that we use the <code>basic_policy</code>
CRTP template:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">struct custom_policy : bom::registry&lt;custom_rtti, bom::policies::vptr_vector&gt; {
};
#define BOOST_OPENMETHOD_DEFAULT_REGISTRY custom_policy</code></pre>
</div>
</div>
<div class="paragraph">
<p>Next, we include the main header. Because <code>BOOST_OPENMETHOD_DEFAULT_REGISTRY</code> is
defined, its value is used for the default policy. Then comes the usual example.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#include &lt;iostream&gt;
#include &lt;boost/openmethod.hpp&gt;
#include &lt;boost/openmethod/compiler.hpp&gt;
using boost::openmethod::virtual_ptr;
BOOST_OPENMETHOD(poke, (std::ostream&amp;, virtual_ptr&lt;Animal&gt;), void);
BOOST_OPENMETHOD_OVERRIDE(
poke, (std::ostream &amp; os, virtual_ptr&lt;Cat&gt; /*cat*/), void) {
os &lt;&lt; "hiss";
}
BOOST_OPENMETHOD_OVERRIDE(
poke, (std::ostream &amp; os, virtual_ptr&lt;Dog&gt; /*dog*/), void) {
os &lt;&lt; "bark";
}
BOOST_OPENMETHOD_CLASSES(Animal, Cat, Dog);
auto main() -&gt; int {
boost::openmethod::initialize();
std::unique_ptr&lt;Animal&gt; a(new Cat);
std::unique_ptr&lt;Animal&gt; b(new Dog);
poke(std::cout, *a); // prints "hiss"
std::cout &lt;&lt; "\n";
poke(std::cout, *b); // prints "bark"
std::cout &lt;&lt; "\n";
return 0;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This programs works even if standard RTTI is disabled.</p>
</div>
</div>
<div class="sect2">
<h3 id="tutorials_deferred_rtti">Deferred RTTI</h3>
<div class="paragraph">
<p>In the previous example, the RTTI system assigns types id statically. It is more
common to allocate them using a global counter, manipulated by static
constructors. This is a problem, because <code>static_type</code> is used by class
registration. It may read the custom type ids <em>before</em> they are have been
initialized.</p>
</div>
<div class="paragraph">
<p>The solution is to add the <code>deferred_static_rtti</code> policy to the policy; it defers
reading the type information until <code>initialize</code> is called.</p>
</div>
<div class="paragraph">
<p>This time let&#8217;s support virtual inheritance as well. First the domain classes:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">struct custom_type_info {
static unsigned last;
unsigned id = ++last;
};
unsigned custom_type_info::last;
struct Animal {
Animal() {
type = type_info.id;
}
virtual ~Animal() = default;
virtual auto cast_impl(unsigned target) -&gt; void* {
if (type_info.id == target) {
return this;
} else {
return nullptr;
}
}
template&lt;class Class&gt;
auto cast() -&gt; Class* {
return reinterpret_cast&lt;Class*&gt;(cast_impl(Class::type_info.id));
}
static custom_type_info type_info;
unsigned type;
};
custom_type_info Animal::type_info;
struct Cat : virtual Animal {
Cat() {
type = type_info.id;
}
virtual auto cast_impl(unsigned target) -&gt; void* {
if (type_info.id == target) {
return this;
} else {
return Animal::cast_impl(target);
}
}
static custom_type_info type_info;
};
custom_type_info Cat::type_info;
// ditto for Dog</code></pre>
</div>
</div>
<div class="paragraph">
<p>The rtti policy is the same, with one more function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">struct custom_rtti : bom::policies::rtti {
// as before
// to support virtual inheritance:
template&lt;typename Derived, typename Base&gt;
static auto dynamic_cast_ref(Base&amp;&amp; obj) -&gt; Derived {
using base_type = std::remove_reference_t&lt;Base&gt;;
if constexpr (std::is_base_of_v&lt;Animal, base_type&gt;) {
return *obj.template cast&lt;std::remove_reference_t&lt;Derived&gt;&gt;();
} else {
abort(); // not supported
}
}
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>Finally, the policy contains an additional policy - <code>deferred_static_rtti</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">struct custom_policy
: bom::policies::basic_policy&lt;
custom_policy, custom_rtti,
bom::policies::deferred_static_rtti, // &lt;-- additional policy
bom::policies::vptr_vector&lt;custom_policy&gt;&gt; {};</code></pre>
</div>
</div>
<div class="paragraph">
<p>The example is the same as in the previous section.</p>
</div>
</div>
<div class="sect2">
<h3 id="tutorials_dynamic_loading">Dynamic Loading</h3>
<div class="paragraph">
<p>OpenMethod supports dynamic loading on operating systems that are capable of
handling C++ templates correctly during dynamic link. A dynamic library can add
classes, methods and overriders to an existing policy. <code>initialize</code> must then be
called to rebuild the dispatch tables.</p>
</div>
<div class="paragraph">
<p>This leads to a problem: any <code>virtual_ptr</code> in existence before <code>initialize</code> is
called again becomes invalid. This also applies to vptrs that are stored inside
objects by <code>inplace_vptr</code>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
This applies only to cases where a dynamic library adds to an <em>existing</em>
policy. Even if the dynamic library itself uses open-methods, for example as an
implementation detail, but it uses its own policy, there is no issue.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The solution is to use a policy that contains the <code>indirect_vptr</code> policy. Instead
of storing the vptr directly, it stores a reference to the vptr.</p>
</div>
<div class="paragraph">
<p>Here is an example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">// dl.hpp
#include &lt;string&gt;
#include &lt;boost/openmethod.hpp&gt;
struct Animal {
virtual ~Animal() {
}
};
struct Herbivore : Animal {};
struct Carnivore : Animal {};
struct Cow : Herbivore {};
struct Wolf : Carnivore {};
struct dynamic : boost::openmethod::default_registry::with&lt;
boost::openmethod::policies::indirect_vptr&gt; {};
template&lt;class Class&gt;
using dyn_vptr = boost::openmethod::virtual_ptr&lt;Class, dynamic&gt;;
BOOST_OPENMETHOD(
encounter, (dyn_vptr&lt;Animal&gt;, dyn_vptr&lt;Animal&gt;), std::string,
dynamic);</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
The policy must be passed to the method as well as the
<code>virtual_ptr</code>s.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The <code>indirect_vptr</code> policy tells <code>virtual_ptr</code> to use a pointer to the vptr. Even
tough the value of the vptr changes when <code>initialize</code> is called, the vptrs are
stored in the same place (the policy&#8217;s <code>static_vptr&lt;Class&gt;</code> variables).</p>
</div>
<div class="paragraph">
<p>We can now register the classes and and provide an overrider:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">// dl_main.cpp
#include &lt;cstring&gt;
#include &lt;iostream&gt;
#include &lt;dlfcn.h&gt;
#include &lt;unistd.h&gt;
#include &lt;boost/openmethod.hpp&gt;
#include &lt;boost/openmethod/interop/std_unique_ptr.hpp&gt;
#include &lt;boost/openmethod/compiler.hpp&gt;
#include "dl.hpp"
BOOST_OPENMETHOD_CLASSES(
Animal, Herbivore, Cow, Wolf, Carnivore, dynamic);
BOOST_OPENMETHOD_OVERRIDE(
encounter, (dyn_vptr&lt;Animal&gt;, dyn_vptr&lt;Animal&gt;), std::string) {
return "ignore\n";
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>At this point we only have one overrider. Animals of all species ignore one
another:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">auto main() -&gt; int {
using namespace boost::openmethod;
initialize&lt;dynamic&gt;();
std::cout &lt;&lt; "Before loading library\n";
auto gracie = make_unique_virtual&lt;Cow, dynamic&gt;();
// Wolf _willy;
// auto willy = virtual_ptr&lt;Wolf, dynamic&gt;(_willy);
auto willy = make_unique_virtual&lt;Wolf, dynamic&gt;();
std::cout &lt;&lt; "Gracie encounters Willy -&gt; "
&lt;&lt; encounter(gracie, willy); // ignore
std::cout &lt;&lt; "Willy encounters Gracie -&gt; "
&lt;&lt; encounter(willy, gracie); // ignore</code></pre>
</div>
</div>
<div class="paragraph">
<p>Let&#8217;s load a dynamic library containing this code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">// dl_shared.cpp
#include &lt;string&gt;
#include &lt;boost/openmethod.hpp&gt;
#include "dl.hpp"
BOOST_OPENMETHOD_OVERRIDE(
encounter, (dyn_vptr&lt;Herbivore&gt;, dyn_vptr&lt;Carnivore&gt;), std::string) {
return "run\n";
}
struct Tiger : Carnivore {};
BOOST_OPENMETHOD_CLASSES(Tiger, Carnivore, dynamic);
extern "C" auto make_tiger() -&gt; Tiger* {
return new Tiger;
}
BOOST_OPENMETHOD_OVERRIDE(
encounter, (dyn_vptr&lt;Carnivore&gt;, dyn_vptr&lt;Herbivore&gt;), std::string) {
return "hunt\n";
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now back to <code>main</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"> char dl_path[4096];
dl_path[readlink("/proc/self/exe", dl_path, sizeof(dl_path))] = 0;
*strrchr(dl_path, '/') = 0;
strcat(dl_path, "/libdl_shared.so");
void* handle = dlopen(dl_path, RTLD_NOW);
if (!handle) {
std::cerr &lt;&lt; "dlopen() failed: " &lt;&lt; dlerror() &lt;&lt; "\n";
exit(1);
}
std::cout &lt;&lt; "\nAfter loading library\n";
boost::openmethod::initialize&lt;dynamic&gt;();
auto make_tiger =
reinterpret_cast&lt;Animal* (*)()&gt;(dlsym(handle, "make_tiger"));
if (!make_tiger) {
std::cerr &lt;&lt; "dlsym() failed: " &lt;&lt; dlerror() &lt;&lt; "\n";
exit(1);
}
std::cout &lt;&lt; "Willy encounters Gracie -&gt; "
&lt;&lt; encounter(willy, gracie); // hunt
{
auto hobbes = std::unique_ptr&lt;Animal&gt;(make_tiger());
std::cout &lt;&lt; "Gracie encounters Hobbes -&gt; "
&lt;&lt; encounter(gracie, *hobbes); // run
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>After unloading the library, we must call <code>initialize</code> again:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"> dlclose(handle);
std::cout &lt;&lt; "\nAfter unloading library\n";
boost::openmethod::initialize&lt;dynamic&gt;();
std::cout &lt;&lt; "Gracie encounters Willy -&gt; "
&lt;&lt; encounter(gracie, willy); // ignore
std::cout &lt;&lt; "Willy encounters Gracie -&gt; "
&lt;&lt; encounter(willy, gracie); // ignore</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="tutorials_reference">Reference</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="ref_overview">Overview</h3>
<div class="sect3">
<h4 id="ref_requirements">Requirements</h4>
<div class="paragraph">
<p>OpenMethod requires C++17 or above. It depends on the following Boost libraries:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Assert</p>
</li>
<li>
<p>Config</p>
</li>
<li>
<p>Core</p>
</li>
<li>
<p>DynamicBitset</p>
</li>
<li>
<p>Mp11</p>
</li>
<li>
<p>Preprocessor</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Boost.Test is also required to build and run the unit tests.</p>
</div>
</div>
<div class="sect3">
<h4 id="ref_installation">Installation</h4>
<div class="paragraph">
<p>The library is headers-only. You can install it system-wide, or add the path to
the <code>include</code> directory to your project&#8217;s include path.</p>
</div>
</div>
<div class="sect3">
<h4 id="ref_namespaces">Namespaces</h4>
<div class="sect4">
<h5 id="ref_boostopenmethod">boost::openmethod</h5>
<div class="paragraph">
<p>The library&#8217;s main namespace. Contains <code>method</code>, <code>virtual_ptr</code> and
<code>virtual_ptr_traits</code>, <code>use_classes</code>, the <code>default_registry</code>, etc.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_boostopenmethodpolicies">boost::openmethod::policies</h5>
<div class="paragraph">
<p>Contains the policy framework.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="ref_headers">Headers</h4>
<div class="sect4">
<h5 id="ref_boostopenmethodcore_hpp">&lt;boost/openmethod/core.hpp&gt;</h5>
<div class="paragraph">
<p>The library&#8217;s main header. Provides <code>method</code>, <code>virtual_ptr</code> and
<code>virtual_ptr_traits</code>, <code>use_classes</code>, the default policy, etc.</p>
</div>
<div class="paragraph">
<p>If <code>BOOST_OPENMETHOD_DEFAULT_REGISTRY</code> is defined before including this header,
its value is used as the default value for the <code>Policy</code> template parameter
throughout the code. Otherwise, <code>boost::openmethod::default_registry</code> is used.
Setting <code>BOOST_OPENMETHOD_DEFAULT_REGISTRY</code> after including the core header has no
effect.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_boostopenmethodmacros_hpp">&lt;boost/openmethod/macros.hpp&gt;</h5>
<div class="paragraph">
<p>Provides <code>BOOST_REGISTER_CLASSES</code>, <code>BOOST_OPENMETHOD</code>,
<code>BOOST_OPENMETHOD_OVERRIDE</code> and other macros.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_boostopenmethod_hpp">&lt;boost/openmethod.hpp&gt;</h5>
<div class="paragraph">
<p>Convenience header. Includes <code>&lt;boost/openmethod/core.hpp&gt;</code> and
<code>&lt;boost/openmethod/macros.hpp&gt;</code>.</p>
</div>
<div class="paragraph">
<p>Also imports <code>boost::openmethod::virtual_ptr</code> in the global namespace. This is
usually regarded as bad practice. The rationale is that OpenMethod emulates a
language feature, and <code>virtual_ptr</code> is equivalent to keyword, similar to
<code>virtual</code>. Besides, the macros are global as well.</p>
</div>
<div class="paragraph">
<p>There are two ways to avoid importing <code>virtual_ptr</code> while still using the
macros:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Define <code>BOOST_OPENMETHOD_NO_GLOBAL_VIRTUAL_PTR</code> before including
<code>&lt;boost/openmethod.hpp&gt;</code>. This disables the import of <code>virtual_ptr</code> in the
global namespace.</p>
</li>
<li>
<p>Include <code>&lt;boost/openmethod/core.hpp&gt;`and `&lt;boost/openmethod/macros.hpp&gt;</code>.</p>
</li>
</ul>
</div>
</div>
<div class="sect4">
<h5 id="ref_boostopenmethodcompiler_hpp">&lt;boost/openmethod/compiler.hpp&gt;</h5>
<div class="paragraph">
<p>Provides <code>intialize</code> and <code>finalize</code>. Typically included only by the translation
unit that contains <code>main</code>, unless dynamic loading is used in other places in the
program.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_boostopenmethodshared_ptr_hpp">&lt;boost/openmethod/interop/std_shared_ptr.hpp&gt;</h5>
<div class="paragraph">
<p>Provides support for using <code>std::shared_ptr</code> in place of plain pointers in
virtual parameters.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_boostopenmethodunique_hpp">&lt;boost/openmethod/unique_.hpp&gt;</h5>
<div class="paragraph">
<p>Provides support for using <code>std::unique_ptr</code> in place of plain pointers in
virtual parameters.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_boostopenmethodinplace_vptr_hpp">&lt;boost/openmethod/inplace_vptr.hpp&gt;</h5>
<div class="paragraph">
<p>Provides support for storing v-table pointers directly in objects, in the same
manner as native virtual functions.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_boostopenmethodpolicies_hpp">&lt;boost/openmethod/policies.hpp&gt;</h5>
<div class="paragraph">
<p>Provides the <code>debug</code> and <code>release</code> policies in the <code>boost::openmethod::policies</code>
namespace, and <code>default_registry</code> in the <code>boost::openmethod</code> namespace, which is
an alias to either <code>debug</code> or <code>release</code>, depending on the value of the
preprocessor symbol <code>NDEBUG</code>.</p>
</div>
<div class="paragraph">
<p>Usually not included directly. Can be used to create custom policies from stock
policies, by forking them and adjusting a few policys.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_boostopenmethodpoliciesbasic_policy_hpp">&lt;boost/openmethod/policies/basic_policy.hpp&gt;</h5>
<div class="paragraph">
<p>Provides the constructs used in the policy framework, essentially
<code>basic_policy</code>, <code>policy</code>, and its abstract subclasses (<code>rtti</code>, <code>extern_vptr</code>,
etc).</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_boostopenmethodpoliciesstd_rtti_hpp">&lt;boost/openmethod/policies/std_rtti.hpp&gt;</h5>
<div class="paragraph">
<p>Implements the <code>rtti</code> policy using standard RTTI.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_boostopenmethodpoliciesminimal_rtti_hpp">&lt;boost/openmethod/policies/minimal_rtti.hpp&gt;</h5>
<div class="paragraph">
<p>Implements the <code>rtti</code> policy using a minimal RTTI implementation. Can be used only with the "final" constructs, or with intrusive v-table pointers.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_boostopenmethodpoliciesvptr_vector_hpp">&lt;boost/openmethod/policies/vptr_vector.hpp&gt;</h5>
<div class="paragraph">
<p>Implements the <code>extern_vptr</code> policy using a vector of pointers.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_boostopenmethodpoliciesvptr_map_hpp">&lt;boost/openmethod/policies/vptr_map.hpp&gt;</h5>
<div class="paragraph">
<p>Implements the <code>extern_vptr</code> policy using a map of pointers.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_boostopenmethodpoliciesfast_perfect_hash_hpp">&lt;boost/openmethod/policies/fast_perfect_hash.hpp&gt;</h5>
<div class="paragraph">
<p>Implements the <code>type_hash</code> policy using a perfect hash function.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_boostopenmethodpoliciesdefault_error_handler_hpp">&lt;boost/openmethod/policies/default_error_handler.hpp&gt;</h5>
<div class="paragraph">
<p>Implements the <code>error_handler</code> policy by routing the error through a
<code>std::function</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_boostopenmethodpoliciesthrow_error_handler_hpp">&lt;boost/openmethod/policies/throw_error_handler.hpp&gt;</h5>
<div class="paragraph">
<p>Implements the <code>error_handler</code> policy by throwing an exception.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_boostopenmethodpoliciesbasic_error_output_hpp">&lt;boost/openmethod/policies/basic_error_output.hpp&gt;</h5>
<div class="paragraph">
<p>Implements the <code>output</code> policy using a lightweight version of
<code>std::ostream</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_boostopenmethodpoliciesbasic_trace_output_hpp">&lt;boost/openmethod/policies/basic_trace_output.hpp&gt;</h5>
<div class="paragraph">
<p>Implements the <code>trace</code> policy using a lightweight version of
<code>std::ostream</code>.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="BOOST_OPENMETHOD">BOOST_OPENMETHOD</h3>
<div class="sect3">
<h4 id="ref_synopsis">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/macros.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">BOOST_OPENMETHOD(NAME, (PARAMETERS...), RETURN_TYPE [, POLICY]);</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="ref_description">Description</h4>
<div class="paragraph">
<p>Declares a method.</p>
</div>
<div class="paragraph">
<p>The macro expands to several constructs:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A <code>struct</code> forward declaration that acts as the method&#8217;s identifier:</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">struct BOOST_OPENMETHOD_ID(NAME);</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>An inline function template, constrained to take the same <code>PARAMETERS</code>,
without the <code>virtual_</code> decorators, returning a <code>RETURN_TYPE</code>. The function
forwards to<br>
<code>method&lt;BOOST_OPENMETHOD_ID(NAME)(PARAMETERS&#8230;&#8203;), RETURN_TYPE, POLICY&gt;::fn</code>.</p>
</li>
<li>
<p>A guide function used to match overriders with the method:</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">auto BOOST_OPENMETHOD_ID(NAME)_guide(...)
-&gt; ::boost::openmethod::method&lt;
BOOST_OPENMETHOD_ID(NAME)(PARAMETERS...), RETURN_TYPE [, POLICY]&gt;;</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<code>NAME</code> must be an <strong>identifier</strong>. Qualified names are not allowed.
</td>
</tr>
</table>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
The default value for <code>POLICY</code> is the value of
<code>BOOST_OPENMETHOD_DEFAULT_REGISTRY</code> at the point <code>&lt;boost/openmethod/core.hpp&gt;</code> is
included. Changing the value of this symbol has no effect after that point.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="BOOST_OPENMETHOD_OVERRIDE">BOOST_OPENMETHOD_OVERRIDE</h3>
<div class="sect3">
<h4 id="ref_synopsis_2">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/macros.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">BOOST_OPENMETHOD_OVERRIDE(NAME, (PARAMETERS...), RETURN_TYPE) {
// body
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="ref_description_2">Description</h4>
<div class="paragraph">
<p><code>BOOST_OPENMETHOD_OVERRIDE</code> adds an overrider to a method.</p>
</div>
<div class="paragraph">
<p>The method is deduced from a call to a method guide function with the
overrider&#8217;s arguments.</p>
</div>
<div class="paragraph">
<p>The macro creates several entities in the current scope.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A class template that acts as a container for the overriders of the methods
called <code>NAME</code>:</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;typename...&gt; BOOST_OPENMETHOD_OVERRIDERS(NAME);</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>A specialization of the container template for the overrider:</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">struct BOOST_OPENMETHOD_OVERRIDERS(NAME)&lt;RETURN_TYPE(PARAMETERS...)&gt; {
static auto fn(PARAMETERS...) -&gt; RETURN_TYPE;
static auto has_next() -&gt; bool;
template&lt;typename... Args&gt;
static auto next(typename... Args) -&gt; RETURN_TYPE;
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>where:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>fn</code> is the overrider function.</p>
</li>
<li>
<p><code>has_next()</code> returns <code>true</code> if a less specialized overrider exists.</p>
</li>
<li>
<p><code>next(Args&#8230;&#8203; args)</code> calls the next most specialized overrider via the
pointer stored in the method&#8217;s <code>next&lt;fn&gt;</code> member variable.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Finally, the macro starts the definition of the overrider function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">auto BOOST_OPENMETHOD_OVERRIDERS(NAME)&lt;RETURN_TYPE(PARAMETERS...)&gt;::fn(
PARAMETERS...) -&gt; RETURN_TYPE</code></pre>
</div>
</div>
<div class="paragraph">
<p>The block following the call to the macro is the body of the function.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<code>NAME</code> must be an <strong>identifier</strong>. Qualified names are not allowed.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="BOOST_OPENMETHOD_INLINE_OVERRIDE">BOOST_OPENMETHOD_INLINE_OVERRIDE</h3>
<div class="sect3">
<h4 id="ref_synopsis_3">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/macros.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">BOOST_OPENMETHOD_INLINE_OVERRIDE(NAME, (PARAMETERS...), RETURN_TYPE) {
// body
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="ref_description_3">Description</h4>
<div class="paragraph">
<p><code>BOOST_OPENMETHOD_INLINE_OVERRIDE</code> performs the same function as
<code>BOOST_OPENMETHOD_OVERRIDE</code>, except that the overrider is defined inline.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<code>NAME</code> must be an <strong>identifier</strong>. Qualified names are not allowed.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="ref_boost_openmethod_declare_overrider">BOOST_OPENMETHOD_DECLARE_OVERRIDER</h3>
<div class="sect3">
<h4 id="ref_synopsis_4">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/macros.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#define BOOST_OPENMETHOD_DECLARE_OVERRIDER(NAME, (PARAMETERS...), RETURN_TYPE)</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="ref_description_4">Description</h4>
<div class="paragraph">
<p>Declares an overrider for a method.</p>
</div>
<div class="paragraph">
<p>The method is deduced from a call to a method guide function with the
overrider&#8217;s arguments.</p>
</div>
<div class="paragraph">
<p>The macro creates several entities in the current scope.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A class template that acts as a container for the overriders of the methods
called <code>NAME</code>:</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;typename...&gt; BOOST_OPENMETHOD_OVERRIDERS(NAME);</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>A specialization of the container template for the overrider:</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">struct BOOST_OPENMETHOD_OVERRIDERS(NAME)&lt;RETURN_TYPE(PARAMETERS...)&gt; {
static auto fn(PARAMETERS...) -&gt; RETURN_TYPE;
static auto has_next() -&gt; bool;
template&lt;typename... Args&gt;
static auto next(typename... Args) -&gt; RETURN_TYPE;
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>where:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>fn</code> is the overrider function.</p>
</li>
<li>
<p><code>has_next()</code> returns <code>true</code> if a less specialized overrider exists.</p>
</li>
<li>
<p><code>next(Args&#8230;&#8203; args)</code> calls the next most specialized overrider via the
pointer stored in the method&#8217;s <code>next&lt;fn&gt;</code> member variable.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><code>BOOST_OPENMETHOD_DECLARE_OVERRIDER</code> can be called in a header file, with a
semicolon after the call. It can be called in a header file, but not multiple
times in the same translation unit.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<code>NAME</code> must be an <strong>identifier</strong>. Qualified names are not allowed.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="ref_boost_openmethod_define_overrider">BOOST_OPENMETHOD_DEFINE_OVERRIDER</h3>
<div class="sect3">
<h4 id="ref_synopsis_5">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/macros.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#define BOOST_OPENMETHOD_DEFINE_OVERRIDER(NAME, (PARAMETERS...), RETURN_TYPE)</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="ref_description_5">Description</h4>
<div class="paragraph">
<p>Defines the body of an overrider declared with
<code>BOOST_OPENMETHOD_DECLARE_OVERRIDER</code>. It should be called in an implementation
file, and followed by a function body.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<code>NAME</code> must be an <strong>identifier</strong>. Qualified names are not allowed.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="ref_boost_openmethod_overrider">BOOST_OPENMETHOD_OVERRIDER</h3>
<div class="sect3">
<h4 id="ref_synopsis_6">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/macros.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#define BOOST_OPENMETHOD_OVERRIDER(NAME, (PARAMETERS...), RETURN_TYPE)</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="ref_description_6">Description</h4>
<div class="paragraph">
<p>Expands to the specialization of the class template that contains the overrider
for with the given name, parameter list and return type.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="BOOST_OPENMETHOD_ID">BOOST_OPENMETHOD_ID</h3>
<div class="sect3">
<h4 id="ref_synopsis_7">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/macros.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#define BOOST_OPENMETHOD_ID(NAME) /* unspecified */</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="ref_description_7">Description</h4>
<div class="paragraph">
<p>Generates a long, obfuscated name from a short name. All the other names
generated by macros are based on this name.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="ref_boost_openmethod_guide">BOOST_OPENMETHOD_GUIDE</h3>
<div class="sect3">
<h4 id="ref_synopsis_8">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/macros.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#define BOOST_OPENMETHOD_GUIDE(NAME) /* unspecified */</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="ref_description_8">Description</h4>
<div class="paragraph">
<p>Expands to the name of the guide function used to match overriders to methods.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="ref_boost_openmethod_overriders">BOOST_OPENMETHOD_OVERRIDERS</h3>
<div class="sect3">
<h4 id="ref_synopsis_9">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/macros.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">#define BOOST_OPENMETHOD_OVERRIDERS(NAME) \
BOOST_PP_CAT(BOOST_OPENMETHOD_ID(NAME), _overriders)</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="ref_description_9">Description</h4>
<div class="paragraph">
<p><code>BOOST_OPENMETHOD_OVERRIDERS</code> expands to the name of the class template that
contains the overriders for all the methods with a given name.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="BOOST_OPENMETHOD_REGISTER">BOOST_OPENMETHOD_REGISTER</h3>
<div class="sect3">
<h4 id="ref_synopsis_10">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/macros.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">BOOST_OPENMETHOD_REGISTER(TYPE);</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="ref_description_10">Description</h4>
<div class="paragraph">
<p>Creates a static instance of <code>TYPE</code>, using a unique generated name.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="BOOST_OPENMETHOD_CLASSES">BOOST_OPENMETHOD_CLASSES</h3>
<div class="sect3">
<h4 id="ref_synopsis_11">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/macros.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">BOOST_OPENMETHOD_CLASSES(CLASSES...[, POLICY]);</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="ref_description_11">Description</h4>
<div class="paragraph">
<p>Register <code>CLASSES</code> in POLICY.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
The default value for <code>POLICY</code> is the value of
<code>BOOST_OPENMETHOD_DEFAULT_REGISTRY</code> when <code>&lt;boost/openmethod/core.hpp&gt;</code> is
included. Subsequently changing it has no retroactive effect.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>This macro is a wrapper around <code>use_classes</code>; see its documentation for more
details.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="BOOST_OPENMETHOD_DEFAULT_REGISTRY">BOOST_OPENMETHOD_DEFAULT_REGISTRY</h3>
<div class="sect3">
<h4 id="ref_description_12">Description</h4>
<div class="paragraph">
<p>The name of the default policy.</p>
</div>
<div class="paragraph">
<p><code>BOOST_OPENMETHOD_DEFAULT_REGISTRY</code> is the default value for the <code>Policy</code> template
parameter of <code>method</code>, <code>use_classes</code>, and other constructs defined in
<code>&lt;boost/openmethod/core.hpp&gt;</code>. If it is not defined,
<code>::boost::openmethod::policy::default_registry</code> is used.</p>
</div>
<div class="paragraph">
<p><code>BOOST_OPENMETHOD_DEFAULT_REGISTRY</code> can be defined by a program to change the
default policy globally. Once <code>&lt;boost/openmethod/core.hpp&gt;</code> has been included,
redefining the symbol has no effect. To override the default policy, proceed as
follows:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Include headers under <code>boost/openmethod/policies/</code> as needed.</p>
</li>
<li>
<p>Create a policy class, and set <code>BOOST_OPENMETHOD_DEFAULT_REGISTRY</code>.</p>
</li>
<li>
<p>Include <code>&lt;boost/openmethod/core.hpp&gt;</code>.</p>
</li>
</ol>
</div>
</div>
</div>
<div class="sect2">
<h3 id="ref_initialize">initialize</h3>
<div class="sect3">
<h4 id="ref_synopsis_12">Synopsis</h4>
<div class="paragraph">
<p>Defined in <code>&lt;boost/openmethod/compiler.hpp&gt;</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod {
template&lt;class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY&gt;
auto initialize() -&gt; /*unspecified*/;
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="ref_description_13">Description</h4>
<div class="paragraph">
<p>Initializes dispatch data for the methods registered in <code>Policy</code>. This function
must be called before any calls to those methods, and after loading or unloading
a dynamic library that adds classes, methods or overriders to <code>Policy</code>.</p>
</div>
<div class="paragraph">
<p>The return value is an object that contains a member variable, <code>report</code>, that
contains the following information:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>std::size_t cells</code>: the number of cells used by the v-tables and the multiple
dispatch tables.</p>
</li>
<li>
<p><code>std::size_t not_implemented</code>: the number of methods that don&#8217;t have an
overrider for at least one combination of virtual arguments.</p>
</li>
<li>
<p><code>std::size_t ambiguous</code>: the number of methods that have more than one
overrider, none of which is more specific than the others, for at least one
combination of virtual arguments.</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect2">
<h3 id="ref_finalize">finalize</h3>
<div class="sect3">
<h4 id="ref_synopsis_13">Synopsis</h4>
<div class="paragraph">
<p>Defined in <code>&lt;boost/openmethod/compiler.hpp&gt;</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod {
template&lt;class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY&gt;
auto finalize() -&gt; void;
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="ref_description_14">Description</h4>
<div class="paragraph">
<p>De-allocates the resources allocated by <code>initialize</code> for the <code>Policy</code>, including
resources allocated by the policys in <code>Policy</code>. Resources are de-allocated in an
arbitrary order. It is not necessary to call <code>finalize</code> between calls to
<code>initialize</code>. It is provided mainly for the benefit of memory leak detection
schemes.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="ref_type_id">type_id</h3>
<div class="sect3">
<h4 id="ref_synopsis_14">Synopsis</h4>
<div class="paragraph">
<p>Defined in <code>&lt;boost/openmethod/policies/basic_policy.hpp&gt;</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod {
using type_id = std::uintptr_t;
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="ref_description_15">Description</h4>
<div class="paragraph">
<p><code>type_id</code> is an unsigned integer type used to identify types. It is wide enough
to contain a pointer.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="ref_vptr_type">vptr_type</h3>
<div class="sect3">
<h4 id="ref_synopsis_15">Synopsis</h4>
<div class="paragraph">
<p>Defined in <code>&lt;boost/openmethod/policies/basic_policy.hpp&gt;</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod {
using vptr_type = const /*unspecified*/ *;
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="ref_description_16">Description</h4>
<div class="paragraph">
<p><code>vptr_type</code> is the type of a pointer to a v-table.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="ref_method">method</h3>
<div class="sect3">
<h4 id="ref_synopsis_16">Synopsis</h4>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod {
template&lt;
typename Method, typename ReturnType,
class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY&gt;
class method;
template&lt;typename Name, typename... Parameters, typename ReturnType, class Policy&gt;
class method&lt;Name(Parameters...), ReturnType, Policy&gt; {
public:
using function_type = ReturnType (*)(CallParameters...);
auto operator()(CallParameters... args) const -&gt; ReturnType;
static method fn;
template&lt;auto... Functions&gt;
struct override;
template&lt;auto Overrider&gt;
static function_type next;
private:
method();
method(const method&amp;) = delete;
method(method&amp;&amp;) = delete;
~method();
};
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="ref_description_17">Description</h4>
<div class="paragraph">
<p><code>method</code> implements an open-method that takes a parameter list - <code>Parameters</code> -
and returns a <code>ReturnType</code>. <code>Name</code> can be any type. Its purpose is to make it
possible to have multiple methods with the same signature. Typically, <code>Name</code> is
a class whose name reflects the method&#8217;s purpose.</p>
</div>
<div class="paragraph">
<p><code>Parameters</code> must contain at least one virtual parameter, i.e. a parameter that
has a type in the form <code>virtual_ptr&lt;T,&#160;Policy&gt;</code> or <code>virtual_&lt;T&gt;</code>. The
dynamic types of the virtual arguments (the arguments corresponding to virtual
parameters in the method&#8217;s signature) are taken into account to select the
overrider to call.</p>
</div>
<div class="paragraph">
<p>A <code>method</code> is attached to a <code>Policy</code>, which influences several parts of the
dispatch mechanism - for example, how to obtain a v-table pointer for an object,
how to report errors, whether to perform sanity checks, etc.</p>
</div>
</div>
<div class="sect3">
<h4 id="ref_members">Members</h4>
<div class="sect4">
<h5 id="ref_constructor">constructor</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">method();</code></pre>
</div>
</div>
<div class="paragraph">
<p>Add the method to the list of methods registered in <code>Policy</code>.</p>
</div>
<div class="paragraph">
<p>The constructor is private. The only instance is the static member variable
<code>fn</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_destructor">destructor</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">~method();</code></pre>
</div>
</div>
<div class="paragraph">
<p>Remove the method from the list of methods registered in <code>Policy</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_operator">operator()</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">auto operator()(CallParameters... args) const -&gt; ReturnType;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Call the method with the arguments <code>args</code>.</p>
</div>
<div class="paragraph">
<p><code>CallParameters</code> are the <code>Parameters</code> without the <code>virtual_</code> decorators. Note
that <code>virtual_ptr</code>s are preserved.</p>
</div>
<div class="paragraph">
<p>The overrider is selected in a process similar to overloaded function
resolution, with extra rules to handle ambiguities. It proceeds as follows:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Form the set of all applicable overriders. An overrider is applicable if it
can be called with the arguments passed to the method.</p>
</li>
<li>
<p>If the set is empty, call the error handler (if present in the policy), then
terminate the program with <code>abort</code></p>
</li>
<li>
<p>Remove the overriders that are dominated by other overriders in the set.
Overrider A dominates overrider B if any of its virtual formal parameters is
more specialized than B&#8217;s, and if none of B&#8217;s virtual parameters is more
specialized than A&#8217;s.</p>
</li>
<li>
<p>If the resulting set contains only one overrider, call it.</p>
</li>
<li>
<p>If the return type is a registered polymorphic type, remove all the
overriders that return a less specific type than the others.</p>
</li>
<li>
<p>If the resulting set contains only one overrider, call it.</p>
</li>
<li>
<p>Otherwise, call one of the remaining overriders. Which overrider is selected
is not specified, but it is the same across calls with the same arguments
types.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>For each virtual argument <code>arg</code>, the dispatch mechanism calls
<code>virtual_traits::peek(arg)</code> and deduces the v-table pointer from the <code>result</code>,
using the first of the following methods that applies:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>If <code>result</code> is a <code>virtual_ptr</code>, get the pointer to the v-table from it.</p>
</li>
<li>
<p>If a function named <code>boost_openmethod_vptr</code> that takes <code>result</code> and returns a
<code>vptr_type</code> exists, call it.</p>
</li>
<li>
<p>Call <code>Policy::dynamic_vptr(result)</code>.</p>
</li>
</ol>
</div>
</div>
<div class="sect4">
<h5 id="ref_fn">fn</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">static method fn;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>method</code>'s unique instance. The method is called via the call
operator on <code>fn</code>: <code>method::fn(args&#8230;&#8203;)</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_override">override</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;auto... Functions&gt;
struct override;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Add <em>Functions</em> to the overriders of <code>method</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_next">next</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;auto Overrider&gt;
static function_type next;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Pointer to the next most specialized overrider after <em>Overrider</em>, i.e. the
overrider that would be called for the same tuple of virtual arguments if
<em>Overrider</em> was not present. Set to <code>nullptr</code> if no such overrider exists.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="method_override">method::override</h3>
<div class="sect3">
<h4 id="ref_synopsis_17">Synopsis</h4>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod {
template&lt;typename Signature, typename ReturnType, class Policy&gt;
template&lt;auto... Functions&gt;
struct method&lt;Signature, ReturnType, Policy&gt;::override {
override();
~override();
};
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Usage:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">method&lt;Signature, ReturnType, Policy&gt;::override&lt;Functions...&gt; some_unique_name;
// at file scope</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="ref_description_18">Description</h4>
<div class="paragraph">
<p><code>override</code>, instantiated as a static object, add one or more overriders to an
open-method.</p>
</div>
<div class="paragraph">
<p><em>Functions</em> must fulfill the following requirements:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Have the same number of formal parameters as the method.</p>
</li>
<li>
<p>Each parameter in the same position as a <code>virtual_ptr&lt;T&gt;</code> in the method&#8217;s
parameter list must be a <code>virtual_ptr&lt;U&gt;</code>, where <em>U</em> is covariant with <em>T</em>. The
<em>Policy</em> of the <code>virtual_ptr</code>s must be the same as the method&#8217;s <em>Policy</em>.</p>
</li>
<li>
<p>Each formal parameter in the same position as a <code>virtual_</code> parameter must have
a type that is covariant with the type of the method&#8217;s parameter.</p>
</li>
<li>
<p>All other formal parameters must have the same type as the method&#8217;s
corresponding parameters.</p>
</li>
<li>
<p>The return type of the overrider must be the same as the method&#8217;s return type
or, if it is a polymorphic type, covariant with the method&#8217;s return type.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="ref_members_2">Members</h4>
<div class="sect4">
<h5 id="ref_constructor_2">constructor</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">override&lt;Functions&gt;::override();</code></pre>
</div>
</div>
<div class="paragraph">
<p>Add <em>Functions</em> to the overriders of <code>method</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="ref_destructor_2">Destructor</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">override&lt;Functions&gt;::~method();</code></pre>
</div>
</div>
<div class="paragraph">
<p>Remove <em>Functions</em> from the overriders of <code>method</code>.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr">virtual_ptr</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis">Synopsis</h4>
<div class="paragraph">
<p><code>virtual_ptr</code> is defined in <code>&lt;boost/openmethod/core.hpp&gt;</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod {
template&lt;class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY&gt;
class virtual_ptr {
public:
static constexpr bool is_smart_ptr = /* see below */;
using element_type = /* see below */;
virtual_ptr();
virtual_ptr(nullptr_t);
template&lt;class Other&gt; virtual_ptr(Other&amp; other);
template&lt;class Other&gt; virtual_ptr(const Other&amp; other);
template&lt;class Other&gt; virtual_ptr(Other&amp;&amp; other);
virtual_ptr&amp; operator =(nullptr_t);
template&lt;class Other&gt; virtual_ptr&amp; operator =(Other&amp; other);
template&lt;class Other&gt; virtual_ptr&amp; operator =(const Other&amp; other);
template&lt;class Other&gt; virtual_ptr&amp; operator =(Other&amp;&amp; other);
template&lt;class Other&gt;
static auto final(Other&amp;&amp; obj);
auto get() const -&gt; element_type*;
auto operator-&gt;() const -&gt; element_type*;
auto operator*() const -&gt; element_type&amp;;
auto pointer() const -&gt; const Class*&amp;;
template&lt;typename Other&gt;
auto cast() const -&gt; virtual_ptr&lt;Other, Policy&gt;;
};
template&lt;class Class&gt;
virtual_ptr(Class&amp;) -&gt; virtual_ptr&lt;Class, BOOST_OPENMETHOD_DEFAULT_REGISTRY&gt;;
template&lt;class Class&gt;
inline auto final_virtual_ptr(Class&amp; obj) -&gt; virtual_ptr&lt;
Class, BOOST_OPENMETHOD_DEFAULT_REGISTRY&gt;;
template&lt;class Policy, class Class&gt;
inline auto final_virtual_ptr(Class&amp; obj) -&gt; virtual_ptr&lt;Class, Policy&gt;;
template&lt;class Left, class Right, class Policy&gt;
auto operator==(
const virtual_ptr&lt;Left, Policy&gt;&amp; left,
const virtual_ptr&lt;Right, Policy&gt;&amp; right) -&gt; bool;
template&lt;class Left, class Right, class Policy&gt;
auto operator!=(
const virtual_ptr&lt;Left, Policy&gt;&amp; left,
const virtual_ptr&lt;Right, Policy&gt;&amp; right) -&gt; bool;
} // namespace boost::openmethod</code></pre>
</div>
</div>
<div class="paragraph">
<p>Defined in <code>&lt;boost/openmethod/interop/std_shared_ptr.hpp&gt;</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod {
template&lt;class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY&gt;
using shared_virtual_ptr = virtual_ptr&lt;std::shared_ptr&lt;Class&gt;, Policy&gt;;
template&lt;
class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY, typename... T&gt;
inline auto make_shared_virtual(T&amp;&amp;... args)
-&gt; shared_virtual_ptr&lt;Class, Policy&gt;;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Defined in <code>&lt;boost/openmethod/interop/std_unique_ptr.hpp&gt;</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod {
template&lt;class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY&gt;
using unique_virtual_ptr = virtual_ptr&lt;std::unique_ptr&lt;Class&gt;, Policy&gt;;
template&lt;
class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY, typename... T&gt;
inline auto make_unique_virtual(T&amp;&amp;... args)
-&gt; unique_virtual_ptr&lt;Class, Policy&gt;;
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description">Description</h4>
<div class="paragraph">
<p><code>virtual_ptr</code> is a wide pointer that combines a pointer to an object and a
pointer to its v-table. The object pointer can be a plain pointer or a smart
pointer. Specializations of <code>virtual_traits</code> are required for smart pointers.
They are provided for <code>std::unique_ptr</code> and <code>std::shared_ptr</code>.</p>
</div>
<div class="paragraph">
<p>A plain <code>virtual_ptr</code> can be constructed from a reference, a smart pointer, or
another <code>virtual_ptr</code>. A smart <code>virtual_ptr</code> can be constructed from a smart
pointer or from a smart <code>virtual_ptr</code>. Usual conversions - from derived to base,
and from non-const to const - are supported.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_members">Members</h4>
<div class="sect4">
<h5 id="virtual_ptr_is_smart_ptr">is_smart_ptr</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">static constexpr bool is_smart_ptr;</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>true</code> if <code>Class</code> is a smart pointer, <code>false</code> otherwise. The value is derived
from <code>virtual_traits&lt;Class, Policy&gt;</code>: if it has a member template called
<code>rebind</code>, <code>Class</code> is considered a smart pointer.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_element_type">element_type</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">using element_type = std::conditional_t&lt;
is_smart_ptr, typename Class::element_type, Class&gt;;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The class of the object pointed to.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_constructors">constructors</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">virtual_ptr(); // 1
virtual_ptr(nullptr_t); // 2
template&lt;class Other&gt; virtual_ptr(Other&amp; other); // 3
template&lt;class Other&gt; virtual_ptr(const Other&amp; other); // 4
template&lt;class Other&gt; virtual_ptr(Other&amp;&amp; other); // 5
template&lt;class Other&gt; virtual_ptr(Other* other); // 6</code></pre>
</div>
</div>
<div class="paragraph">
<p>(1) Default constructor. Sets the v-table pointer to <code>nullptr</code>. If <code>Class</code> is
<em>not</em> a smart pointer, the value of object pointer is is undefined.</p>
</div>
<div class="paragraph">
<p>(2) Sets both the object and v-table pointers to <code>nullptr</code>.</p>
</div>
<div class="paragraph">
<p>(3), (4) For plain <code>virtual_ptr</code>s, <code>other</code> must be either a lvalue
reference to an object of a registered class, or a <code>virtual_ptr</code> (plain or
smart). For smart <code>virtual_ptr</code>s, <code>other</code> must be a reference to a smart
pointer, or a reference to a smart <code>virtual_ptr</code>.</p>
</div>
<div class="paragraph">
<p>(5) Constructs a <code>virtual_ptr</code> from a smart pointer or a smart <code>virtual_ptr</code>.
The object pointer is moved from <code>other</code>.</p>
</div>
<div class="paragraph">
<p>(6) Constructs a <code>virtual_ptr</code> from a plain pointer. Available only for plain
<code>virtual_ptr</code>s.</p>
</div>
<div class="paragraph">
<p>If <code>other</code> is also a <code>virtual_ptr</code>, the v-table pointer is copied from it.
Otherwise, it is deduced from the object. The <code>Policy</code> must be the same for both
<code>virtual_ptr</code>s.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_assignment_operators">assignment operators</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">virtual_ptr&amp; operator =(nullptr_t); // 1
template&lt;class Other&gt; virtual_ptr&amp; operator =(Other&amp; other); // 2
template&lt;class Other&gt; virtual_ptr&amp; operator =(const Other&amp; other); // 3
template&lt;class Other&gt; virtual_ptr&amp; operator =(Other&amp;&amp; other); // 4
template&lt;class Other&gt; virtual_ptr&amp; operator =(Other* other); // 5</code></pre>
</div>
</div>
<div class="paragraph">
<p>(1) Sets both the object and v-table pointers to <code>nullptr</code>.</p>
</div>
<div class="paragraph">
<p>(2), (3) For plain <code>virtual_ptr</code>s, <code>other</code> must be either a lvalue
reference to an object of a registered class, or a <code>virtual_ptr</code> (plain or
smart). For smart <code>virtual_ptr</code>s, <code>other</code> must be a reference to a smart
pointer, or a reference to a smart <code>virtual_ptr</code>.</p>
</div>
<div class="paragraph">
<p>(4) Moves <code>other</code> to this <code>virtual_ptr</code>. If <code>other</code> is a smart pointer or a
smart virtual pointer, the object pointer is moved from <code>other</code>.</p>
</div>
<div class="paragraph">
<p>(5) Sets the object pointer to <code>other</code>. Available only for plain
<code>virtual_ptr</code>s.</p>
</div>
<div class="paragraph">
<p>If <code>other</code> is also a <code>virtual_ptr</code>, the v-table pointer is copied from it.
Otherwise, it is deduced from the object. The <code>Policy</code> must be the same for both
<code>virtual_ptr</code>s.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_final">final</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Other&gt;
static auto final(Other&amp;&amp; obj);</code></pre>
</div>
</div>
<div class="paragraph">
<p>Constructs a <code>virtual_ptr</code> from a reference to an object, or from a smart
pointer. It is assumed that the static and dynamic types are the same. The
v-table pointer is initialized from the <code>Policy::static_vptr</code> for the class,
which needs not be polymorphic.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_get">get</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">auto get() const -&gt; element_type*;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Returns a pointer to the object.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_operator">operator&#8594;</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">auto operator-&gt;() const -&gt; element_type*;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Returns a pointer to the object.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_operator_2">operator*</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">auto operator*() const -&gt; element_type&amp;;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Returns a reference to the object.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_pointer">pointer</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">auto pointer() const;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Returns a reference to the object pointer, which can be either a plain pointer
or a smart pointer.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_cast">cast</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;typename Other&gt;
auto cast() const -&gt; virtual_ptr&lt;Other, Policy&gt;;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Returns a <code>virtual_ptr</code> to the same object, cast to <code>Other</code>.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_deduction_guide">Deduction guide</h4>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Class&gt;
virtual_ptr(Class&amp;) -&gt; virtual_ptr&lt;Class, BOOST_OPENMETHOD_DEFAULT_REGISTRY&gt;;</code></pre>
</div>
</div>
<hr>
</div>
<div class="sect3">
<h4 id="virtual_ptr_non_members">Non-members</h4>
<div class="sect4">
<h5 id="virtual_ptr_virtual_shared_ptr">virtual_shared_ptr</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY&gt;
using virtual_shared_ptr = virtual_ptr&lt;std::shared_ptr&lt;Class&gt;, Policy&gt;;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Convenience alias for <code>virtual_ptr&lt;std::shared_ptr&lt;Class&gt;, Policy&gt;</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_virtual_unique_ptr">virtual_unique_ptr</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY&gt;
using virtual_unique_ptr = virtual_ptr&lt;std::unique_ptr&lt;Class&gt;, Policy&gt;;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Convenience alias for <code>virtual_ptr&lt;std::unique_ptr&lt;Class&gt;, Policy&gt;</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_final_virtual_ptr">final_virtual_ptr</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Policy, class Class&gt;
inline auto final_virtual_ptr(Class&amp;&amp; obj);
template&lt;class Class&gt;
inline auto final_virtual_ptr(Class&amp;&amp; obj);</code></pre>
</div>
</div>
<div class="paragraph">
<p>Utility functions, forwarding to <code>virtual_ptr&lt;Class, Policy&gt;::final</code>.</p>
</div>
<div class="paragraph">
<p>If <code>Policy</code> is not specified, <code>BOOST_OPENMETHOD_DEFAULT_REGISTRY</code> is used.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_make_shared_virtual">make_shared_virtual</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;
class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY, typename... T&gt;
inline auto make_shared_virtual(T&amp;&amp;... args)
-&gt; shared_virtual_ptr&lt;Class, Policy&gt;;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Creates an object using <code>std::make_shared</code> and returns a <code>virtual_shared_ptr</code> to
it. The v-table pointer is initialized from the the <code>Policy::static_vptr</code> for
the class, which needs not be polymorphic.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_make_unique_virtual">make_unique_virtual</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;
class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY, typename... T&gt;
inline auto make_unique_virtual(T&amp;&amp;... args)
-&gt; unique_virtual_ptr&lt;Class, Policy&gt;;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Creates an object using <code>std::make_unique</code> and returns a <code>virtual_unique_ptr</code> to
it. The v-table pointer is initialized from the the <code>Policy::static_vptr</code> for
the class, which needs not be polymorphic.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_operator_3">operator==</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Left, class Right, class Policy&gt;
auto operator==(
const virtual_ptr&lt;Left, Policy&gt;&amp; left,
const virtual_ptr&lt;Right, Policy&gt;&amp; right) -&gt; bool;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Compares two <code>virtual_ptr</code> objects for equality.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_operator_4">operator!=</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Left, class Right, class Policy&gt;
auto operator!=(
const virtual_ptr&lt;Left, Policy&gt;&amp; left,
const virtual_ptr&lt;Right, Policy&gt;&amp; right) -&gt; bool;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Compares two <code>virtual_ptr</code> objects for inequality.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_virtual_traits">virtual_traits</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_2">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/core.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod {
template&lt;class, class&gt;
struct virtual_traits; // not defined
template&lt;class Class, class Policy&gt;
struct virtual_traits&lt;..., Policy&gt; {
using virtual_type = ...;
static auto peek(const T&amp; arg) -&gt; const ...&amp;;
template&lt;typename Derived&gt; static auto cast(T&amp; obj) -&gt; ...;
template&lt;class Other&gt; using rebind = ...; // for smart virtual pointers
};
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_2">Description</h4>
<div class="paragraph">
<p>Specializations of <code>virtual_traits</code> provide an interface for <code>method</code> and
<code>virtual_ptr</code> to manipulate virtual arguments.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_specializations">Specializations</h4>
<div class="paragraph">
<p>Specializations are provided for:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>virtual_ptr&lt;T, Policy&gt;</code></p>
</li>
<li>
<p><code>const virtual_ptr&lt;T, Policy&gt;&amp;</code></p>
</li>
<li>
<p><code>T&amp;</code></p>
</li>
<li>
<p><code>T&amp;&amp;</code></p>
</li>
<li>
<p><code>T*</code></p>
</li>
<li>
<p><code>std::shared_ptr&lt;T&gt;</code>: defined in &lt;boost/openmethod/interop/std_shared_ptr.hpp&gt;</p>
</li>
<li>
<p><code>const std::shared_ptr&lt;T&gt;&amp;</code>: defined in &lt;boost/openmethod/interop/std_shared_ptr.hpp&gt;</p>
</li>
<li>
<p><code>std::unique_ptr&lt;T&gt;</code>: defined in &lt;boost/openmethod/interop/std_unique_ptr.hpp&gt;</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_members_2">Members</h4>
<div class="sect4">
<h5 id="virtual_ptr_virtual_type">virtual_type</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">using virtual_type = ...;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The class used for method selection. It must be registered in Policy.</p>
</div>
<div class="paragraph">
<p>For example, <code>virtual_type</code> in the following specializations are all <code>Class</code>:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>virtual_traits&lt;virtual_ptr&lt;Class, Policy&gt;&gt;</code></p>
</li>
<li>
<p><code>virtual_traits&lt;const virtual_ptr&lt;std::shared_ptr&lt;Class&gt;&amp;, Policy&gt;</code></p>
</li>
<li>
<p><code>virtual_traits&lt;Class&amp;, Policy&gt;</code></p>
</li>
<li>
<p><code>virtual_traits&lt;const std::shared_ptr&lt;Class&gt;&amp;, Policy&gt;</code></p>
</li>
</ul>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_peek">peek</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">static auto peek(T arg) -&gt; const ...&amp;;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Returns a value for the purpose of obtaining a v-table pointer for <code>arg</code>.</p>
</div>
<div class="paragraph">
<p>For example, <code>peek</code> returns a <code>const T&amp;</code> for a <code>T&amp;</code>, a <code>const T&amp;</code>, a <code>T&amp;&amp;</code>, and
a <code>std::shared_ptr&lt;T&gt;</code>; and a <code>const virtual_ptr&lt;Class, Policy&gt;&amp;</code> for a
<code>const virtual_ptr&lt;Class, Policy&gt;&amp;</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_cast_2">cast</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;typename Derived&gt;
static decltype(auto) cast(T&amp; obj);</code></pre>
</div>
</div>
<div class="paragraph">
<p>Casts argument <code>obj</code> to the type expected by an overrider.</p>
</div>
<div class="paragraph">
<p>For example, if a method takes a <code>virtual_&lt;Animal&amp;&gt;</code>, an overrider for <code>Cat&amp;</code>
uses <code>virtual_traits</code> to cast a <code>Animal&amp;</code> to a <code>Cat&amp;</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_rebind">rebind</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Other&gt; using rebind = ...;</code></pre>
</div>
</div>
<div class="paragraph">
<p>For smart pointers only. Rebinds the smart pointer to a different type. For
example, <code>virtual_traits&lt;std::shared_ptr&lt;T&gt;, Policy&gt;::rebind&lt;U&gt;</code> is
<code>std::shared_ptr&lt;U&gt;</code>.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_use_classes">use_classes</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_3">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/core.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod {
template&lt;class... Classes, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY&gt;
struct use_classes {
use_classes();
~use_classes();
};
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Usage:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">use_classes&lt;Classes...&gt; some_unique_name; // at file scope</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_3">Description</h4>
<div class="paragraph">
<p><code>use_classes</code>, instantiated as a static object, registers <code>Classes</code> in <code>Policy</code>.</p>
</div>
<div class="paragraph">
<p>Classes potentially involved in a method definition, an overrider, or a method
call must be registered via <code>use_classes</code>. A class may be registered multiple
times. A class and its direct bases must be listed together in one or more
instantiations of <code>use_classes</code>.</p>
</div>
<div class="paragraph">
<p>Virtual and multiple inheritance are supported, as long as they don&#8217;t result in
a class lattice that contains repeated inheritance.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
The default value for <code>Policy</code> is the value of
<code>BOOST_OPENMETHOD_DEFAULT_REGISTRY</code> when <code>&lt;boost/openmethod/core.hpp&gt;</code> is
included. Subsequently changing it has no retroactive effect.
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_members_3">Members</h4>
<div class="sect4">
<h5 id="virtual_ptr_constructor">constructor</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">use_classes();</code></pre>
</div>
</div>
<div class="paragraph">
<p>Registers <code>Classes</code> and their inheritance relationships in <code>Policy</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_destructor">destructor</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">~use_classes();</code></pre>
</div>
</div>
<div class="paragraph">
<p>Removes <code>Classes</code> and their inheritance relationships from <code>Policy</code>.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_virtual">virtual_</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_4">Synopsis</h4>
<div class="paragraph">
<p>Defined in <code>&lt;boost/openmethod/core.hpp&gt;</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod {
template&lt;typename T&gt;
struct virtual_;
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_4">Description</h4>
<div class="paragraph">
<p>Marks a formal parameter of a method as virtual. Requires a specialization of
<code>virtual_traits</code> for <code>T</code> and the <code>Policy</code> of the method. Specializations for
<code>T&amp;</code>, <code>T&amp;&amp;</code>, <code>T*</code>, <code>std::unique_ptr&lt;T&gt;</code>, <code>std::shared_ptr&lt;T&gt;</code> and <code>const
std::shared_ptr&lt;T&gt;&amp;</code> are provided. See the documentation of <code>virtual_traits</code> for
more information.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_inplace_vptr">inplace_vptr</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_5">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/inplace_vptr.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod {
template&lt;class Class, class Policy = BOOST_OPENMETHOD_DEFAULT_REGISTRY&gt;
class inplace_vptr {
protected:
inplace_vptr();
~inplace_vptr();
friend auto boost_openmethod_vptr(const Class&amp; obj) -&gt; vptr_type;
};
template&lt;class Class, class Base, class... MoreBases&gt;
class inplace_vptr {
protected:
inplace_vptr();
~inplace_vptr();
friend auto boost_openmethod_vptr(const Class&amp; obj) -&gt; vptr_type;
// if sizeof(MoreBases...) &gt; 0
};
} // namespace boost::openmethod</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_5">Description</h4>
<div class="paragraph">
<p><code>inplace_vptr</code> is a CRTP class template that embeds and manages a vptr across a
class hierarchy.</p>
</div>
<div class="paragraph">
<p>If <code>Class</code> has no <code>Bases</code>, <code>inplace_vptr</code> adds a <code>boost_openmethod_vptr</code> private
member to <code>Class</code>. In either case, it sets the vptr to the v-table of <code>Class</code>
from <code>Policy</code>. It also creates a <code>boost_openmethod_vptr</code> friend function that
takes a a <code>const Class&amp;</code> and returns the embedded vptr.</p>
</div>
<div class="paragraph">
<p>If <code>Class</code> has has more than one base, the <code>boost_openmethod_vptr</code> friend
function is also created. It returns one of the embedded vptrs (it doesn&#8217;t
matter which one, as they all have the same value). This is to resolve
ambiguities</p>
</div>
<div class="paragraph">
<p>As part of its implementation, <code>inplace_vptr</code> may also declare one or two free
functions (<code>boost_openmethod_policy</code> and <code>boost_openmethod_bases</code>) at certain
levels of the hierarchy.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_members_4">Members</h4>
<div class="sect4">
<h5 id="virtual_ptr_constructor_2">constructor</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">inplace_vptr();</code></pre>
</div>
</div>
<div class="paragraph">
<p>Sets the vptr to the v-table for Class, obtained from <code>Policy</code>. If <code>Policy</code>
contains <code>indirect_vptr</code>, an additional level of indirection is added, thus
preserving the validity of the pointer across calls to <code>initialize</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_destructor_2">destructor</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">~inplace_vptr();</code></pre>
</div>
</div>
<div class="paragraph">
<p>For each <code>Base</code>, sets the vptr to the v-table for that base.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_free_functions">Free Functions</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">auto boost_openmethod_vptr(const Class&amp; obj) -&gt; vptr_type;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Returns the vptr embedded in <code>obj</code>.
## abstract_policy</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_6">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/policies/basic_policy.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod::policies {
struct abstract_policy {};
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_6">Description</h4>
<div class="paragraph">
<p><code>abstract_policy</code> is a required base class for a policy. It makes it possible
for meta-functions such as <code>use_classes</code> to discriminate between user classes
and the (optional) policy class.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_domain">domain</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_7">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/policies/basic_policy.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod::policies {
template&lt;class Policy&gt;
struct domain {
template&lt;class Class&gt; static vptr_type static_vptr;
// unspecified members
};
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_7">Description</h4>
<div class="paragraph">
<p><code>domain</code> is a registry of classes and methods registered in a <em>Policy</em>,
and their dispatch tables.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_members_5">Members</h4>
<div class="sect4">
<h5 id="virtual_ptr_static_vptr">static_vptr</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Class&gt;
static vptr_type static_vptr;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Contains the pointer to the v-table for <em>Class</em>. Set by <code>initialize</code>.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_basic_policy">basic_policy</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_8">Synopsis</h4>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod {
namespace policies {
template&lt;class Policy, class... Facets&gt;
struct basic_policy : abstract_policy, domain&lt;Policy&gt;, Facets... {
template&lt;class Facet&gt;
static constexpr bool has = /*unspecified*/;
template&lt;class NewPolicy&gt;
using fork = /*unspecified*/;
template&lt;class... Facets&gt;
using with = /*unspecified*/;
template&lt;class... Facets&gt;
using without = /*unspecified*/;
};
struct release : basic_policy&lt;release, ...&gt; {};
struct debug : release::add&lt;...&gt; {};
} // policies
#ifdef NDEBUG
using default_registry = policies::release;
#else
using default_registry = policies::debug;
#endif
} // boost::openmethod</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_headers">Headers</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/policies/basic_policy.hpp&gt;. Also available via
<code>&lt;boost/openmethod/core.hpp&gt;</code> and <code>&lt;boost/openmethod.hpp&gt;</code>.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_8">Description</h4>
<div class="paragraph">
<p><code>basic_policy</code> implements a policy, which consists of a a collection of methods,
classes, dispatch data, and policys, which specify how to obtain a pointer to a
v-table from an object, how to report errors, whether to perform runtime sanity
checks, etc.</p>
</div>
<div class="paragraph">
<p><code>basic_policy</code> has state. It uses the Curiously Recurring Template Pattern to
allow distinct policies to have distinct sets of static variables.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_members_6">Members</h4>
<div class="sect4">
<h5 id="virtual_ptr_has">has</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Facet&gt;
static constexpr bool has;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Evaluates to <code>true</code> if <em>Policy</em> contains <em>Facet</em>.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_fork">fork</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class NewPolicy&gt;
using fork;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Creates a new policy from an existing one. <em>NewPolicy</em> does not share static
variables with the original <em>Policy</em>. The new policy does not retain any
knowledge of the classes and methods registered in the original.</p>
</div>
<div class="paragraph">
<p><code>fork</code> forks the policys in the policy as well: any policy instantiated from a
class template is assumed to take a policy as its first template argument. The
template is re-instantiated with the new policy as the first arguments, while
the other arguments remain the same.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_with">with</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class... Facets&gt;
using with;</code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Requires</dt>
<dd>
<p><em>Facets</em> is a list of classes that derive from <code>policy</code>.</p>
</dd>
<dt class="hdlist1">Returns</dt>
<dd>
<p>A new policy containing <em>Facets</em>, and the policys from the original
that do not have the same category as <em>Facets</em>.</p>
</dd>
<dt class="hdlist1">Examples</dt>
<dd>
<div class="ulist">
<ul>
<li>
<p><code>struct dyn_load : default_registry::fork&lt;dyn_load&gt;::with&lt;indirect_vptr&gt; {};</code><br>
Creates a policy just like <code>default_registry</code>, with an extra indirection added
to the v-table pointers. This policy is suitable for use with dynamic loading.</p>
</li>
<li>
<p><code>struct release_with_diags : release::fork&lt;release_with_diags&gt;::with&lt;basic_error_output&lt;release_with_diags&gt;&gt; {};</code><br>
Creates a policy just like <code>release</code>, except that it prints a diagnostic
message before terminating with <code>abort()</code>.</p>
</li>
<li>
<p><code>struct default_throw : default_registry::fork&lt;default_throw&gt;::with&lt;throw_error_handler&gt; {};</code><br>
Creates a policy just like <code>default_registry</code>, except that it reports errors by
throwing exceptions, instead of calling a <code>std::function</code> like the default
error handler does.</p>
</li>
</ul>
</div>
</dd>
</dl>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_without">without</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class... Facets&gt;
using without;</code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Requires</dt>
<dd>
<p><em>Facets</em> is a list of policy categories.</p>
</dd>
<dt class="hdlist1">Returns</dt>
<dd>
<p>A new policy containing the policys from the original that do not have
the same category as <em>Facets</em>.</p>
</dd>
<dt class="hdlist1">Examples</dt>
<dd>
<div class="ulist">
<ul>
<li>
<p><code>struct use_map : default_registry::fork&lt;use_map&gt;::with&lt;vptr_map&lt;use_map&gt;&gt;::without&lt;type_hash&gt; {};</code><br>
Creates a policy just like <code>default_registry</code>, except that it stores pointers to
v-table in a <code>std::unordered_map</code>. Also removes the hash function, since it
will not be used.</p>
</li>
</ul>
</div>
</dd>
</dl>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_non_members_2">Non-members</h4>
<div class="sect4">
<h5 id="virtual_ptr_release">release</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">struct release;</code></pre>
</div>
</div>
<div class="paragraph">
<p>A policy that contains policys <code>std_rtti</code>, <code>fast_perfect_hash</code>, <code>vptr_vector</code> and
<code>default_error_handler</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_debug">debug</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">struct debug;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>release</code> policy with additional policy implementations <code>runtime_checks</code>,
<code>basic_error_output</code> and basic_trace_output.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<code>debug</code> extends <code>release</code> but it does not a fork it. Both policies use the
same <code>domain</code>.
</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_default_registry">default_registry</h5>
<div class="paragraph">
<p>An alias for <code>release</code> if <code>NDEBUG</code> is defined, and for <code>debug</code> otherwise.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_policy">policy</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_9">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/policies/basic_policy.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod::policies {
struct policy {
static auto finalize() -&gt; void;
};
} // boost::openmethod::policies</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_9">Description</h4>
<div class="paragraph">
<p><code>policy</code> is the base class of all policys. It provides an empty <code>finalize</code> static
function which can be overriden (via shadowing) by derived classes.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_members_7">Members</h4>
<div class="sect4">
<h5 id="virtual_ptr_finalize">finalize</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">static auto finalize() -&gt; void;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Does nothing.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_rtti">rtti</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_10">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/policies/basic_policy.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod::policies {
struct rtti : policy {};
} // boost::openmethod::policies</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_10">Description</h4>
<div class="paragraph">
<p>The <code>rtti</code> policy provides type information for classes and objects, implements
downcast in presence of virtual inheritance, and writes descriptions of types to
an <code>ostream</code>-like object.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_requirements">Requirements</h4>
<div class="sect4">
<h5 id="virtual_ptr_is_polymorphic">is_polymorphic</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Class&gt;
static constexpr bool is_polymorphic;</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>true</code> if <code>Class</code> is polymorphic.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_static_type">static_type</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Class&gt;
static auto static_type() -&gt; type_id;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Returns a <code>type_id</code> for <code>Class</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_dynamic_type">dynamic_type</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Class&gt;
static auto dynamic_type(const Class&amp; obj) -&gt; type_id;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Returns a <code>type_id</code> for an object&#8217;s dynamic type.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_type_name">type_name</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;typename Stream&gt;
static auto type_name(type_id type, Stream&amp; stream) -&gt; void;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Writes a description of <code>type</code> to <code>stream</code>.</p>
</div>
<div class="paragraph">
<p>This requirement is optional. <code>rtti</code> provides a default implementation that writes <code>typeid({type})</code> to <code>stream</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_type_index">type_index</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">static auto type_index(type_id type) -&gt; /* unspecified */;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Returns a unique key for <code>type</code>. Required only for RTTI systems that assign more
than one type "identifiers" to a type. For example, standard RTTI allows
implementations to have multiple instances of <code>std::type_info</code> for the same
type.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_dynamic_cast_ref">dynamic_cast_ref</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;typename D, typename B&gt;
static auto dynamic_cast_ref(B&amp;&amp; obj) -&gt; D;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Casts <code>obj</code> to <code>D</code>. Required only if using virtual inheritance.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_std_rtti">std_rtti</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_11">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/policies/std_rtti.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod::policies {
struct std_rtti : rtti {
template&lt;class Class&gt;
static auto static_type() -&gt; type_id;
template&lt;class Class&gt;
static auto dynamic_type(const Class&amp; obj) -&gt; type_id;
template&lt;typename Stream&gt;
static auto type_name(type_id type, Stream&amp; stream) -&gt; void;
static auto type_index(type_id type) -&gt; std::type_index;
template&lt;typename D, typename B&gt;
static auto dynamic_cast_ref(B&amp;&amp; obj) -&gt; D;
};
} // boost::openmethod::policies</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_11">Description</h4>
<div class="paragraph">
<p><code>std_rtti</code> is an implementation of the <code>rtti</code> policy that uses standard RTTI.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_members_8">Members</h4>
<div class="sect4">
<h5 id="virtual_ptr_static_type_2">static_type</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Class&gt;
static auto static_type() -&gt; type_id;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Return the address of <code>Class&#8217;s `type_info</code>, cast to a <code>type_id</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_dynamic_type_2">dynamic_type</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Class&gt;
static auto dynamic_type(const Class&amp; obj) -&gt; type_id;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Return the address of <code>obj</code>'s <code>type_info</code>, cast to a <code>type_id</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_type_name_2">type_name</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;typename Stream&gt;
static auto type_name(type_id type, Stream&amp; stream) -&gt; void;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Write the demangled name of the class identified by <code>type</code> to <code>stream</code>.
Execute <code>stream &lt;&lt; reinterpret_cast&lt;const std::type_info*&gt;(type)&#8594;name()</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_type_index_2">type_index</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">static auto type_index(type_id type) -&gt; /*unspecified*/;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Return <code>std::type_index(<strong>reinterpret_cast&lt;const std::type_info</strong>&gt;(type))</code>.</p>
</div>
<div class="paragraph">
<p>The function is required because C++ does <strong>not</strong> guarantee that there is a single
instance of <code>std::type_info</code> for each specific type.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_dynamic_cast_ref_2">dynamic_cast_ref</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;typename Derived, typename Base&gt;
static auto dynamic_cast_ref(Base&amp;&amp; obj) -&gt; Derived;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Cast <code>obj</code> using the <code>dynamic_cast</code> operator.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_deferred_static_rtti">deferred_static_rtti</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_12">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/policies/basic_policy.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod::policies {
struct deferred_static_rtti : rtti {};
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_12">Description</h4>
<div class="paragraph">
<p><code>deferred_static_rtti</code> is a policy that defers collection of static type ids.</p>
</div>
<div class="paragraph">
<p>Some custom RTTI systems rely on static constructors to assign type ids.
OpenMethod itself relies on static constructors to register classes, methods and
overriders, calling the <code>static_type</code> function from the <code>rtti</code> policy in the
process. This can result in collecting the type ids <em>before</em> they have been
initialized. Adding this policy to a policy moves the collection of type ids to
<code>initialize</code>.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_minimal_rtti">minimal_rtti</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_13">Synopsis</h4>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">struct minimal_rtti : rtti {
template&lt;class Class&gt;
static constexpr bool is_polymorphic = false;
template&lt;typename Class&gt;
static auto static_type() -&gt; type_id;
};</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_13">Description</h4>
<div class="paragraph">
<p><code>minimal_rtti</code> is an implementation of the <code>rtti</code> policy that only uses static
type information.</p>
</div>
<div class="paragraph">
<p><code>minimal_rtti</code> provides the only function strictly required for the <code>rtti</code>
policy.</p>
</div>
<div class="paragraph">
<p>This policy can be used in programs that call methods solely via
<code>virtual_ptr</code>s created with the "final" constructs. Virtual inheritance
is not supported. Classes are not required to be polymorphic.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_members_9">Members</h4>
<div class="sect4">
<h5 id="virtual_ptr_is_polymorphic_2">is_polymorphic</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Class&gt;
static constexpr bool is_polymorphic = false;</code></pre>
</div>
</div>
<div class="paragraph">
<p>This policy does not support polymorphic classes.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_static_type_3">static_type</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Class&gt;
static auto static_type() -&gt; type_id;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Returns the address of a local static <code>char</code> variable, cast to <code>type_id</code>.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_extern_vptr">extern_vptr</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_14">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/policies/basic_policy.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod::policies {
struct extern_vptr : policy {};
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_14">Description</h4>
<div class="paragraph">
<p><code>extern_vptr</code> is a policy that stores and returns pointers to v-tables for
registered classes.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_requirements_2">Requirements</h4>
<div class="sect4">
<h5 id="virtual_ptr_register_vptrs">register_vptrs</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;typename ForwardIterator&gt;
auto register_vptrs(ForwardIterator first, ForwardIterator last) -&gt; void;</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>ForwardIterator</code> is a forward iterator over a range of objects that contain
information about the type ids and the vptr of a registered class. They have the
following member functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">auto type_id_begin() const -&gt; type_id_forward_iterator;
auto type_id_end() const -&gt; type_id_forward_iterator;
auto vptr() const -&gt; const vptr_type&amp;;</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>type_id_begin</code> and <code>type_id_end</code> return iterators delimiting a range of
`type_id`s for a class.</p>
</div>
<div class="paragraph">
<p><code>vptr</code> returns a <em>reference</em> to a <em>static</em> variable containing a pointer to the
v-table for a the class. Its value is set by <code>initialize</code>. While the value of
the variable changes with each call to <code>initialize</code>, the variable itself remains
the same.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_indirect_vptr">indirect_vptr</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_15">Synopsis</h4>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">struct indirect_vptr : policy {};</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_15">Description</h4>
<div class="paragraph">
<p><code>indirect_vptr</code> is a policy that makes <code>virtual_ptr</code>s and <code>inplace_vptr</code> use
pointers to pointers to v-tables, instead of straight pointers. As a
consequence, they remain valid after a call to <code>initialize</code>.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_requirements_3">Requirements</h4>
<div class="paragraph">
<p>None. The policy is its own implementation.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_vptr_vector">vptr_vector</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_16">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/policies/vptr_vector.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod::policies {
template&lt;class Policy&gt;
class vptr_vector : Base {
public:
template&lt;typename ForwardIterator&gt;
static auto register_vptrs(ForwardIterator first, ForwardIterator last) -&gt; void;
template&lt;class Class&gt;
static auto dynamic_vptr(const Class&amp; arg) -&gt; const vptr_type&amp;;
};
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_16">Description</h4>
<div class="paragraph">
<p><code>vptr_vector</code> is an implementation or <code>external_vptr</code> that keeps the pointers to
the v-tables in a <code>std::vector</code>. If <code>Policy</code> contains <code>indirect_vptr</code>, a level
of indirection is added, making the policy usable in presence of dynamic
loading.</p>
</div>
<div class="paragraph">
<p><code>Policy</code> is the policy containing the policy.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_members_10">Members</h4>
<div class="sect4">
<h5 id="virtual_ptr_register_vptrs_2">register_vptrs</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;typename ForwardIterator&gt;
auto register_vptrs(ForwardIterator first, ForwardIterator last) -&gt; void;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Stores the pointers to v-tables in a vector, indexed by the (possibly hashed)
<code>type_id`s of the classes registered in `Policy</code>.</p>
</div>
<div class="paragraph">
<p>If <code>Policy</code> contains a <code>type_hash</code> policy, call its <code>hash_initialize</code>
function, and uses it to convert the <code>type_id</code>s to an index.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_dynamic_vptr">dynamic_vptr</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Class&gt;
auto dynamic_vptr(const Class&amp; object) -&gt; const vptr_type&amp;;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Returns a pointer to the v-table for <code>object</code> (by reference).</p>
</div>
<div class="paragraph">
<p>Obtains a <code>type_id</code> for <code>object</code> using <code>Policy::dynamic_type</code>. If <em>Policy</em>
contains a <code>type_hash</code> policy, uses it to convert the result to an index;
otherwise, uses the <code>type_id</code> as the index.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_vptr_map">vptr_map</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_17">Synopsis</h4>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod::policies {
### Synopsis
template&lt;class Policy, class MapAdaptor = mp11::mp_quote&lt;std::unordered_map&gt;&gt;
class vptr_map : public extern_vptr {
public:
template&lt;typename ForwardIterator&gt;
static auto register_vptrs(ForwardIterator first, ForwardIterator last) -&gt; void;
template&lt;class Class&gt;
static auto dynamic_vptr(const Class&amp; arg) -&gt; const vptr_type&amp;;
};
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_17">Description</h4>
<div class="paragraph">
<p><code>vptr_map</code> is an implementation of <code>external_vptr that stores the pointers to
the v-tables in a map. If `Policy</code> contains <code>indirect_vptr</code>, a level of
indirection is added, making the policy usable in presence of dynamic loading.</p>
</div>
<div class="paragraph">
<p><code>Policy</code> is the policy containing the policy.</p>
</div>
<div class="paragraph">
<p><code>MapAdaptor</code> is a Boost.Mp11 quoted metafunction that returns a map type.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_members_11">Members</h4>
<div class="sect4">
<h5 id="virtual_ptr_register_vptrs_3">register_vptrs</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;typename ForwardIterator&gt;
auto register_vptrs(ForwardIterator first, ForwardIterator last) -&gt; void;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Stores the pointers to v-tables in a <em>Map</em>.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_dynamic_vptr_2">dynamic_vptr</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Class&gt;
auto dynamic_vptr(const Class&amp; object) -&gt; const vptr_type&amp;;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Returns a pointer to the v-table for <code>object</code> (by reference).</p>
</div>
<div class="paragraph">
<p>If <em>Policy</em> contains the <code>runtime_checks</code> policy, checks if <em>Class</em> is
registered. If it is not, and <em>Policy</em> contains a <code>error_handler</code> policy, calls
its <code>error</code> function; then calls <code>abort</code>.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_type_hash">type_hash</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_18">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/policies/basic_policy.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod::policies {
struct type_hash : policy {};
} // boost::openmethod::policies</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_18">Description</h4>
<div class="paragraph">
<p><code>type_hash</code> is a policy that provides a hash function for a fixed set of
<code>type_id</code>s.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_requirements_4">Requirements</h4>
</div>
<div class="sect3">
<h4 id="virtual_ptr_hash_type_id">hash_type_id</h4>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">static auto hash_type_id(type_id type) -&gt; type_id;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Returns the hash of <code>type</code>.</p>
</div>
<div class="sect4">
<h5 id="virtual_ptr_hash_initialize">hash_initialize</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;typename ForwardIterator&gt;
static auto hash_initialize(ForwardIterator first, ForwardIterator last)
-&gt; Report;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Finds a hash function for the <code>type_id</code>s in the range <code>[first, last)</code>.
<code>ForwardIterator</code> is the same as in <code>vptr_vector::register_vptrs</code>.</p>
</div>
<div class="paragraph">
<p><code>hash_initialize</code> returns a <code>Report</code> object which is required to have two
members, <code>first</code> and <code>last</code>, which define the range <code>[first, last)</code> of the
possible output values of the hash function.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_fast_perfect_hash">fast_perfect_hash</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_19">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/policies/fast_perfect_hash.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">class fast_perfect_hash : type_hash
{
public:
static auto hash_type_id(type_id type) -&gt; type_id;
template&lt;typename ForwardIterator&gt;
static auto hash_initialize(ForwardIterator first, ForwardIterator last) -&gt; Report;
};</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_19">Description</h4>
<div class="paragraph">
<p><code>fast_perfect_hash</code> implements a very fast, perfect (but not minimal) hash
function for <code>type_id</code>s.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_members_12">Members</h4>
<div class="paragraph">
<p>Find two factors</p>
</div>
<div class="sect4">
<h5 id="virtual_ptr_hash_type_id_2">hash_type_id</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">static auto hash_type_id(type_id type) -&gt; type_id;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Returns <code>(type * M) &gt;&gt; S</code>, where <code>M</code> and <code>S</code> are factors found by
<code>hash_initialize</code>.</p>
</div>
<div class="paragraph">
<p>If the policy has a <code>runtime_checks</code> policy, <code>hash_type_id</code> checks that <code>type</code>
corresponds to a registered class. If not, it reports a <code>unknown_class_error</code>
using the policy&#8217;s error_handler policy, if present, then calls <code>abort</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_hash_initialize_2">hash_initialize</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;typename ForwardIterator&gt;
auto hash_initialize(ForwardIterator first, ForwardIterator last) -&gt; Report;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Finds factors <code>M</code> and <code>S</code> such that <code>hash_type_id</code> is a collision-free hash
function.</p>
</div>
<div class="paragraph">
<p>If no such factors cannot be found, <code>hash_initialize</code> reports a
<code>hash_search_error</code> using the policy&#8217;s error_handler policy, if present, the
calls <code>abort</code>.</p>
</div>
<div class="paragraph">
<p>If the policy has a <code>trace</code> policy, <code>hash_initialize</code> uses it to write a
summary of the search.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_error_handler">error_handler</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_20">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/policies/basic_policy.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod {
namespace policies {
struct error_handler;
}
struct openmethod_error {};
struct not_implemented_error : openmethod_error {
type_id method;
std::size_t arity;
static constexpr std::size_t max_types = 16;
type_id types[max_types];
};
struct unknown_class_error : openmethod_error {
type_id type;
};
struct hash_search_error : openmethod_error {
std::size_t attempts;
std::size_t buckets;
};
struct type_mismatch_error : openmethod_error {
type_id type;
};
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_20">Description</h4>
<div class="paragraph">
<p><code>error_handler</code> is a policy that handles errors.</p>
</div>
<div class="paragraph">
<p>When an error is encountered, either during <code>initialize</code> or method dispatch, the
program is terminated via a call to <code>abort</code>. If this policy is present in the
policy, its <code>error</code> function is called with an error object. It can prevent
termination by throwing an exception.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_requirements_5">Requirements</h4>
<div class="paragraph">
<p>Implementations of <code>error_handler</code> must provide the following functions:</p>
</div>
<div class="sect4">
<h5 id="virtual_ptr_error">error</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">static auto error(const T&amp;) -&gt; void;</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_default_error_handler">default_error_handler</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_21">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/policies/default_error_handler.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod::policies {
template&lt;class Policy&gt;
class default_error_handler : public error_handler {
public:
using error_variant = std::variant&lt;
openmethod_error, not_implemented_error, unknown_class_error,
hash_search_error, type_mismatch_error, static_slot_error,
static_stride_error&gt;;
using function_type = std::function&lt;void(const error_variant&amp; error)&gt;;
template&lt;class Error&gt;
static auto error(const Error&amp; error) -&gt; void;
static auto set_error_handler(error_handler_type handler) -&gt; function_type;
};
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_21">Description</h4>
<div class="paragraph">
<p><code>default_error_handler</code> is an implementation of <code>error_handler</code> that calls a
<code>std::function</code> to handle the error.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_members_13">Members</h4>
<div class="sect4">
<h5 id="virtual_ptr_error_2">error</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Error&gt;
static auto error(const Error&amp; error) -&gt; void;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Calls the function last set via <code>set_error_handler</code> or, if it was never called,
and if <em>Policy</em> contains an <code>output</code> policy, use it to print a description
of <code>error</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_error_3">error</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">static auto set_error_handler(function_type handler) -&gt; function_type;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Sets <code>handler</code> as the function to call in case of error.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_throw_error_handler">throw_error_handler</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_22">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/policies/throw_error_handler.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod::policies {
struct throw_error_handler : error_handler {
template&lt;class Error&gt;
[[noreturn]] static auto error(const Error&amp; error) -&gt; void;
};
} // boost::openmethod::policies</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_22">Description</h4>
<div class="paragraph">
<p>throw_error_handler is an implementation of the <code>error_handler</code> policy that
throws the error as an exception.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_members_14">Members</h4>
<div class="sect4">
<h5 id="virtual_ptr_error_4">error</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">template&lt;class Error&gt;
[[noreturn]] static auto error(const Error&amp; error) -&gt; void;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Throws <code>error</code>.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_basic_error_output">basic_error_output</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_23">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/policies/basic_error_output.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod::policies {
template&lt;class Policy, typename Stream = /*unspecified*/&gt;
struct basic_error_output : output {
static Stream error_stream;
};
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_23">Description</h4>
<div class="paragraph">
<p><code>basic_error_output</code> is an implementation of <code>output</code> that writes error
messages to a <code>LightweightOutputStream</code>.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_members_15">Members</h4>
<div class="sect4">
<h5 id="virtual_ptr_error_stream">error_stream</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">Stream error_stream;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Initialized by the default constructor of <code>Stream</code>. It is the responsibility of
the program to initializate it if needed, e.g., for a <code>std::ofstream</code>, to open
it.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_basic_trace_output">basic_trace_output</h3>
<div class="sect3">
<h4 id="virtual_ptr_synopsis_24">Synopsis</h4>
<div class="paragraph">
<p>Defined in &lt;boost/openmethod/policies/basic_trace_output.hpp&gt;.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">namespace boost::openmethod::policies {
template&lt;class Policy, typename Stream = /*unspecified*/&gt;
struct basic_trace_output : trace {
static bool trace_enabled;
static Stream trace_stream;
};
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_description_24">Description</h4>
<div class="paragraph">
<p><code>basic_error_output</code> is an implementation of <code>trace</code> that writes error
messages to a <code>LightweightOutputStream</code>.</p>
</div>
</div>
<div class="sect3">
<h4 id="virtual_ptr_members_16">Members</h4>
<div class="sect4">
<h5 id="virtual_ptr_trace_enabled">trace_enabled</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">static bool trace_enabled;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Set to <code>true</code> if environment variable <code>BOOST_OPENMETHOD_TRACE</code> is set to <code>1</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="virtual_ptr_trace_stream">trace_stream</h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++">static Stream trace_stream;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Initialized by the default constructor of <code>Stream</code>. It is the responsibility of
the program to prepare it for output if needed, e.g., for a <code>std::ofstream</code>, to
open it.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="virtual_ptr_restrictedoutputstream">LightweightOutputStream</h3>
<div class="sect3">
<h4 id="virtual_ptr_description_25">Description</h4>
<div class="paragraph">
<p>LightweightOutputStream is a concept describing a <code>std::ostream</code>-like class with
a reduced set of operations.</p>
</div>
<div class="paragraph">
<p>While convenient, <code>std::ostream</code> and its implementations constitute a sizeable
piece of code, which may make it unsuitable for certain applications. OpenMethod
uses a small subset of the operations supported by <code>std::ostream</code>. By default,
the library uses a lightweight implementation based on the C stream functions.</p>
</div>
<div class="paragraph">
<p>Implementations of <code>LightweightOutputStream</code> provide the following functions:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>LightweightOutputStream&amp; operator&lt;&lt;(LightweightOutputStream&amp; os, const char* str)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Write a null-terminated string <code>str</code> to <code>os</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>LightweightOutputStream&amp; operator&lt;&lt;(LightweightOutputStream&amp; os, const std::string_view&amp; view)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Write a view to `os</p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>LightweightOutputStream&amp; operator&lt;&lt;(LightweightOutputStream&amp; os, const void* value)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Write a representation of a pointer to <code>os</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>LightweightOutputStream&amp; operator&lt;&lt;(LightweightOutputStream&amp; os, std::size_t value)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Write an unsigned integer to <code>os</code></p>
</div></div></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2025-06-22 13:38:14 -0400
</div>
</div>
</body>
</html>