<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Function Object-Based Overloading of Operator Dot</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"></meta>
<meta name="keywords" content="overloading, operator, smart, objects, references, C++, proposal, ISO/IEC, JTC1, SC22, WG21, N4495"></meta>

<style type="text/css">

#docinfo table {
  border: none;
  border-spacing: 0px;
}

h2 {
  clear: both;
}

@media screen and (min-width: 1280px) {

#info {
  position: fixed;
  left: 80%;
  top: 0;
}

#docinfo, #toc { width: 95%; }

#body {
  width: 80%;
}

}

#toc ul { margin: 0; }
#toc li { margin: 0; }

#toc { margin-bottom: 1em; }

/* github-like markdown */

body {
  font-family: Helvetica, arial, sans-serif;
  font-size: 14px;
  line-height: 1.6;
  padding-top: 10px;
  padding-bottom: 10px;
  background-color: white;
  padding: 30px;
  color: #333;
}
 
body > *:first-child {
  margin-top: 0 !important;
}
 
body > *:last-child {
  margin-bottom: 0 !important;
}
 
a {
  color: #4183C4;
  text-decoration: none;
}
 
a.absent {
  color: #cc0000;
}
 
a.anchor {
  display: block;
  padding-left: 30px;
  margin-left: -30px;
  cursor: pointer;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
}
 
h1, h2, h3, h4, h5, h6 {
  margin: 20px 0 10px;
  padding: 0;
  font-weight: bold;
  -webkit-font-smoothing: antialiased;
  cursor: text;
  position: relative;
}
 
h2:first-child, h1:first-child, h1:first-child + h2, h3:first-child, h4:first-child, h5:first-child, h6:first-child {
  margin-top: 0;
  padding-top: 0;
}
 
h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor {
  text-decoration: none;
}
 
h1 tt, h1 code {
  font-size: inherit;
}
 
h2 tt, h2 code {
  font-size: inherit;
}
 
h3 tt, h3 code {
  font-size: inherit;
}
 
h4 tt, h4 code {
  font-size: inherit;
}
 
h5 tt, h5 code {
  font-size: inherit;
}
 
h6 tt, h6 code {
  font-size: inherit;
}
 
h1 {
  font-size: 28px;
  color: black;
}
 
h2 {
  font-size: 24px;
  border-bottom: 1px solid #cccccc;
  color: black;
}
 
h3 {
  font-size: 18px;
}
 
h4 {
  font-size: 16px;
}
 
h5 {
  font-size: 14px;
}
 
h6 {
  color: #777777;
  font-size: 14px;
}
 
p, blockquote, ul, ol, dl, li, table, pre {
  margin: 15px 0;
}
 
hr {
  background: transparent url("http://tinyurl.com/bq5kskr") repeat-x 0 0;
  border: 0 none;
  color: #cccccc;
  height: 4px;
  padding: 0;
}
 
body > h2:first-child {
  margin-top: 0;
  padding-top: 0;
}
 
body > h1:first-child {
  margin-top: 0;
  padding-top: 0;
}
 
body > h1:first-child + h2 {
  margin-top: 0;
  padding-top: 0;
}
 
body > h3:first-child, body > h4:first-child, body > h5:first-child, body > h6:first-child {
  margin-top: 0;
  padding-top: 0;
}
 
a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
  margin-top: 0;
  padding-top: 0;
}
 
h1 p, h2 p, h3 p, h4 p, h5 p, h6 p {
  margin-top: 0;
}
 
li p.first {
  display: inline-block;
}
 
ul, ol {
  padding-left: 30px;
}
 
ul :first-child, ol :first-child {
  margin-top: 0;
}
 
ul :last-child, ol :last-child {
  margin-bottom: 0;
}
 
dl {
  padding: 0;
}
 
dl dt {
  font-size: 14px;
  font-weight: bold;
  font-style: italic;
  padding: 0;
  margin: 15px 0 5px;
}
 
dl dt:first-child {
  padding: 0;
}
 
dl dt > :first-child {
  margin-top: 0;
}
 
dl dt > :last-child {
  margin-bottom: 0;
}
 
dl dd {
  margin: 0 0 15px;
  padding: 0 15px;
}
 
dl dd > :first-child {
  margin-top: 0;
}
 
dl dd > :last-child {
  margin-bottom: 0;
}
 
blockquote {
  border-left: 4px solid #dddddd;
  padding: 0 15px;
  color: #777777;
}
 
blockquote > :first-child {
  margin-top: 0;
}
 
blockquote > :last-child {
  margin-bottom: 0;
}
 
table {
  padding: 0;
}
table tr {
  border-top: 1px solid #cccccc;
  background-color: white;
  margin: 0;
  padding: 0;
}
 
table tr:nth-child(2n) {
  background-color: #f8f8f8;
}
 
table tr th {
  font-weight: bold;
  border: 1px solid #cccccc;
  text-align: left;
  margin: 0;
  padding: 6px 13px;
}
 
table tr td {
  border: 1px solid #cccccc;
  text-align: left;
  margin: 0;
  padding: 6px 13px;
}
 
table tr th :first-child, table tr td :first-child {
  margin-top: 0;
}
 
table tr th :last-child, table tr td :last-child {
  margin-bottom: 0;
}
 
img {
  max-width: 100%;
}
 
span.frame {
  display: block;
  overflow: hidden;
}
 
span.frame > span {
  border: 1px solid #dddddd;
  display: block;
  float: left;
  overflow: hidden;
  margin: 13px 0 0;
  padding: 7px;
  width: auto;
}
 
span.frame span img {
  display: block;
  float: left;
}
 
span.frame span span {
  clear: both;
  color: #333333;
  display: block;
  padding: 5px 0 0;
}
 
span.align-center {
  display: block;
  overflow: hidden;
  clear: both;
}
 
span.align-center > span {
  display: block;
  overflow: hidden;
  margin: 13px auto 0;
  text-align: center;
}
 
span.align-center span img {
  margin: 0 auto;
  text-align: center;
}
 
span.align-right {
  display: block;
  overflow: hidden;
  clear: both;
}
 
span.align-right > span {
  display: block;
  overflow: hidden;
  margin: 13px 0 0;
  text-align: right;
}
 
span.align-right span img {
  margin: 0;
  text-align: right;
}
 
span.float-left {
  display: block;
  margin-right: 13px;
  overflow: hidden;
  float: left;
}
 
span.float-left span {
  margin: 13px 0 0;
}
 
span.float-right {
  display: block;
  margin-left: 13px;
  overflow: hidden;
  float: right;
}
 
span.float-right > span {
  display: block;
  overflow: hidden;
  margin: 13px auto 0;
  text-align: right;
}
 
code, tt {
  margin: 0 2px;
  padding: 0 5px;
  white-space: nowrap;
  border: 1px solid #eaeaea;
  background-color: #f8f8f8;
  border-radius: 3px;
}
 
pre code {
  margin: 0;
  padding: 0;
  white-space: pre;
  border: none;
  background: transparent;
}
 
.highlight pre {
  background-color: #f8f8f8;
  border: 1px solid #cccccc;
  font-size: 13px;
  line-height: 19px;
  overflow: auto;
  padding: 6px 10px;
  border-radius: 3px;
}
 
pre {
  background-color: #f8f8f8;
  border: 1px solid #cccccc;
  font-size: 13px;
  line-height: 19px;
  overflow: auto;
  padding: 6px 10px;
  border-radius: 3px;
}
 
pre code, pre tt {
  background-color: transparent;
  border: none;
}

/*

Highlight style
github.com style (c) Vasily Polovnyov <vast@whiteants.net>

*/

.hljs {
  display: block;
  overflow-x: auto;
  padding: 0.5em;
  color: #333;
  background: #f8f8f8;
  -webkit-text-size-adjust: none;
}

.hljs-comment,
.diff .hljs-header,
.hljs-javadoc {
  color: #998;
  font-style: italic;
}

.hljs-keyword,
.css .rule .hljs-keyword,
.hljs-winutils,
.nginx .hljs-title,
.hljs-subst,
.hljs-request,
.hljs-status {
  color: #333;
  font-weight: bold;
}

.hljs-number,
.hljs-hexcolor,
.ruby .hljs-constant {
  color: #008080;
}

.hljs-string,
.hljs-tag .hljs-value,
.hljs-phpdoc,
.hljs-dartdoc,
.tex .hljs-formula {
  color: #d14;
}

.hljs-title,
.hljs-id,
.scss .hljs-preprocessor {
  color: #900;
  font-weight: bold;
}

.hljs-list .hljs-keyword,
.hljs-subst {
  font-weight: normal;
}

.hljs-class .hljs-title,
.hljs-type,
.vhdl .hljs-literal,
.tex .hljs-command {
  color: #458;
  font-weight: bold;
}

.hljs-tag,
.hljs-tag .hljs-title,
.hljs-rule .hljs-property,
.django .hljs-tag .hljs-keyword {
  color: #000080;
  font-weight: normal;
}

.hljs-attribute,
.hljs-variable,
.lisp .hljs-body,
.hljs-name {
  color: #008080;
}

.hljs-regexp {
  color: #009926;
}

.hljs-symbol,
.ruby .hljs-symbol .hljs-string,
.lisp .hljs-keyword,
.clojure .hljs-keyword,
.scheme .hljs-keyword,
.tex .hljs-special,
.hljs-prompt {
  color: #990073;
}

.hljs-built_in {
  color: #0086b3;
}

.hljs-preprocessor,
.hljs-pragma,
.hljs-pi,
.hljs-doctype,
.hljs-shebang,
.hljs-cdata {
  color: #999;
  font-weight: bold;
}

.hljs-deletion {
  background: #fdd;
}

.hljs-addition {
  background: #dfd;
}

.diff .hljs-change {
  background: #0086b3;
}

.hljs-chunk {
  color: #aaa;
}


</style>

<script>
!function(e){"undefined"!=typeof exports?e(exports):(window.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return window.hljs}))}(function(e){function n(e){return e.replace(/&/gm,"&amp;").replace(/</gm,"&lt;").replace(/>/gm,"&gt;")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0==t.index}function a(e){var n=(e.className+" "+(e.parentNode?e.parentNode.className:"")).split(/\s+/);return n=n.map(function(e){return e.replace(/^lang(uage)?-/,"")}),n.filter(function(e){return N(e)||/no(-?)highlight|plain|text/.test(e)})[0]}function i(e,n){var t,r={};for(t in e)r[t]=e[t];if(n)for(t in n)r[t]=n[t];return r}function o(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3==i.nodeType?a+=i.nodeValue.length:1==i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function u(e,r,a){function i(){return e.length&&r.length?e[0].offset!=r[0].offset?e[0].offset<r[0].offset?e:r:"start"==r[0].event?e:r:e.length?e:r}function o(e){function r(e){return" "+e.nodeName+'="'+n(e.value)+'"'}l+="<"+t(e)+Array.prototype.map.call(e.attributes,r).join("")+">"}function u(e){l+="</"+t(e)+">"}function c(e){("start"==e.event?o:u)(e.node)}for(var s=0,l="",f=[];e.length||r.length;){var g=i();if(l+=n(a.substr(s,g[0].offset-s)),s=g[0].offset,g==e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g==e&&g.length&&g[0].offset==s);f.reverse().forEach(o)}else"start"==g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return l+n(a.substr(s))}function c(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,o){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var u={},c=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");u[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?c("keyword",a.k):Object.keys(a.k).forEach(function(e){c(e,a.k[e])}),a.k=u}a.lR=t(a.l||/\b\w+\b/,!0),o&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&o.tE&&(a.tE+=(a.e?"|":"")+o.tE)),a.i&&(a.iR=t(a.i)),void 0===a.r&&(a.r=1),a.c||(a.c=[]);var s=[];a.c.forEach(function(e){e.v?e.v.forEach(function(n){s.push(i(e,n))}):s.push("self"==e?a:e)}),a.c=s,a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,o);var l=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=l.length?t(l.join("|"),!0):{exec:function(){return null}}}}r(e)}function s(e,t,a,i){function o(e,n){for(var t=0;t<n.c.length;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function f(e,n){return!a&&r(n.iR,e)}function g(e,n){var t=E.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function p(e,n,t,r){var a=r?"":x.classPrefix,i='<span class="'+a,o=t?"":"</span>";return i+=e+'">',i+n+o}function d(){if(!L.k)return n(y);var e="",t=0;L.lR.lastIndex=0;for(var r=L.lR.exec(y);r;){e+=n(y.substr(t,r.index-t));var a=g(L,r);a?(B+=a[1],e+=p(a[0],n(r[0]))):e+=n(r[0]),t=L.lR.lastIndex,r=L.lR.exec(y)}return e+n(y.substr(t))}function h(){if(L.sL&&!w[L.sL])return n(y);var e=L.sL?s(L.sL,y,!0,M[L.sL]):l(y);return L.r>0&&(B+=e.r),"continuous"==L.subLanguageMode&&(M[L.sL]=e.top),p(e.language,e.value,!1,!0)}function b(){return void 0!==L.sL?h():d()}function v(e,t){var r=e.cN?p(e.cN,"",!0):"";e.rB?(k+=r,y=""):e.eB?(k+=n(t)+r,y=""):(k+=r,y=t),L=Object.create(e,{parent:{value:L}})}function m(e,t){if(y+=e,void 0===t)return k+=b(),0;var r=o(t,L);if(r)return k+=b(),v(r,t),r.rB?0:t.length;var a=u(L,t);if(a){var i=L;i.rE||i.eE||(y+=t),k+=b();do L.cN&&(k+="</span>"),B+=L.r,L=L.parent;while(L!=a.parent);return i.eE&&(k+=n(t)),y="",a.starts&&v(a.starts,""),i.rE?0:t.length}if(f(t,L))throw new Error('Illegal lexeme "'+t+'" for mode "'+(L.cN||"<unnamed>")+'"');return y+=t,t.length||1}var E=N(e);if(!E)throw new Error('Unknown language: "'+e+'"');c(E);var R,L=i||E,M={},k="";for(R=L;R!=E;R=R.parent)R.cN&&(k=p(R.cN,"",!0)+k);var y="",B=0;try{for(var C,j,I=0;;){if(L.t.lastIndex=I,C=L.t.exec(t),!C)break;j=m(t.substr(I,C.index-I),C[0]),I=C.index+j}for(m(t.substr(I)),R=L;R.parent;R=R.parent)R.cN&&(k+="</span>");return{r:B,value:k,language:e,top:L}}catch(S){if(-1!=S.message.indexOf("Illegal"))return{r:0,value:n(t)};throw S}}function l(e,t){t=t||x.languages||Object.keys(w);var r={r:0,value:n(e)},a=r;return t.forEach(function(n){if(N(n)){var t=s(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}}),a.language&&(r.second_best=a),r}function f(e){return x.tabReplace&&(e=e.replace(/^((<[^>]+>|\t)+)/gm,function(e,n){return n.replace(/\t/g,x.tabReplace)})),x.useBR&&(e=e.replace(/\n/g,"<br>")),e}function g(e,n,t){var r=n?E[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function p(e){var n=a(e);if(!/no(-?)highlight|plain|text/.test(n)){var t;x.useBR?(t=document.createElementNS("http://www.w3.org/1999/xhtml","div"),t.innerHTML=e.innerHTML.replace(/\n/g,"").replace(/<br[ \/]*>/g,"\n")):t=e;var r=t.textContent,i=n?s(n,r,!0):l(r),c=o(t);if(c.length){var p=document.createElementNS("http://www.w3.org/1999/xhtml","div");p.innerHTML=i.value,i.value=u(c,o(p),r)}i.value=f(i.value),e.innerHTML=i.value,e.className=g(e.className,n,i.language),e.result={language:i.language,re:i.r},i.second_best&&(e.second_best={language:i.second_best.language,re:i.second_best.r})}}function d(e){x=i(x,e)}function h(){if(!h.called){h.called=!0;var e=document.querySelectorAll("pre code");Array.prototype.forEach.call(e,p)}}function b(){addEventListener("DOMContentLoaded",h,!1),addEventListener("load",h,!1)}function v(n,t){var r=w[n]=t(e);r.aliases&&r.aliases.forEach(function(e){E[e]=n})}function m(){return Object.keys(w)}function N(e){return w[e]||w[E[e]]}var x={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},w={},E={};return e.highlight=s,e.highlightAuto=l,e.fixMarkup=f,e.highlightBlock=p,e.configure=d,e.initHighlighting=h,e.initHighlightingOnLoad=b,e.registerLanguage=v,e.listLanguages=m,e.getLanguage=N,e.inherit=i,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="\\b(0[xX][a-fA-F0-9]+|(\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e});hljs.registerLanguage("cpp",function(t){var i={keyword:"false int float while private char catch export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const struct for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using true class asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue wchar_t inline delete alignof char16_t char32_t constexpr decltype noexcept nullptr static_assert thread_local restrict _Bool complex _Complex _Imaginary intmax_t uintmax_t int8_t uint8_t int16_t uint16_t int32_t uint32_t  int64_t uint64_t int_least8_t uint_least8_t int_least16_t uint_least16_t int_least32_t uint_least32_t int_least64_t uint_least64_t int_fast8_t uint_fast8_t int_fast16_t uint_fast16_t int_fast32_t uint_fast32_t int_fast64_t uint_fast64_t intptr_t uintptr_t atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong atomic_wchar_t atomic_char16_t atomic_char32_t atomic_intmax_t atomic_uintmax_t atomic_intptr_t atomic_uintptr_t atomic_size_t atomic_ptrdiff_t atomic_int_least8_t atomic_int_least16_t atomic_int_least32_t atomic_int_least64_t atomic_uint_least8_t atomic_uint_least16_t atomic_uint_least32_t atomic_uint_least64_t atomic_int_fast8_t atomic_int_fast16_t atomic_int_fast32_t atomic_int_fast64_t atomic_uint_fast8_t atomic_uint_fast16_t atomic_uint_fast32_t atomic_uint_fast64_t",built_in:"std string cin cout cerr clog stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf"};return{aliases:["c","cc","h","c++","h++","hpp"],k:i,i:"</",c:[t.CLCM,t.CBCM,t.QSM,{cN:"string",b:"'\\\\?.",e:"'",i:"."},{cN:"number",b:"\\b(\\d+(\\.\\d*)?|\\.\\d+)(u|U|l|L|ul|UL|f|F)"},t.CNM,{cN:"preprocessor",b:"#",e:"$",k:"if else elif endif define undef warning error line pragma",c:[{b:/\\\n/,r:0},{b:'include\\s*[<"]',e:'[>"]',k:"include",i:"\\n"},t.CLCM]},{b:"\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",e:">",k:i,c:["self"]},{b:t.IR+"::",k:i},{bK:"new throw return else",r:0},{cN:"function",b:"("+t.IR+"\\s+)+"+t.IR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:i,c:[{b:t.IR+"\\s*\\(",rB:!0,c:[t.TM],r:0},{cN:"params",b:/\(/,e:/\)/,k:i,r:0,c:[t.CBCM]},t.CLCM,t.CBCM]}]}});

window.onload = function()
{
	/* force all code elements to be C++ */
    var code_elements = document.getElementsByTagName("code");
    for(var i=0; i<code_elements.length; ++i)
    {
	    code_elements[i].className = 'cpp';
    }

    hljs.initHighlighting();
}
</script>

</head>
<body>

  <h1>Function Object-Based Overloading of Operator Dot</h1>

<div id="info">

<div id="docinfo">
  <table border="1">
    <tr> <th>Doc. No.:</th> <td>P0060R0</td> </tr>
    <tr> <th>Date:</th>     <td>2015-09-18</td> </tr>
    <tr> <th>Project:</th>  <td>Programming Language C++, Evolution Working Group</td> </tr>
    <tr> <th>Reply To:</th> <td>Mathias Gaunard &lt;<a href="mailto:mgaunard@bloomberg.net">mgaunard@bloomberg.net</a>&gt;,<br>
                                Dietmar Kühl &lt;<a href="mailto:dkuhl@bloomberg.net">dkuhl@bloomberg.net</a>&gt;</td> </tr>
  </table>
  </div>

<div id="toc">
<p>Table of Contents:</p>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#changelog">Changelog</a><ul>
<li><a href="#p0060r0---2015-09-18">P0060R0 - 2015-09-18</a></li>
<li><a href="#n4495---2015-05-22">N4495 - 2015-05-22</a></li>
</ul></li>
<li><a href="#motivation">Motivation</a></li>
<li><a href="#design-and-specification">Design and Specification</a><ul>
<li><a href="#lookup-rules">Lookup rules</a></li>
<li><a href="#member-functions-and-scope-capture">Member functions and scope capture</a></li>
<li><a href="#extension-to-reflection">Extension to reflection</a></li>
</ul></li>
<li><a href="#properties-of-the-design">Properties of the Design</a><ul>
<li><a href="#controlling-reference-leaking">Controlling reference leaking</a></li>
<li><a href="#overloading-operator.-on-multiple-objects">Overloading operator.() on multiple objects</a></li>
<li><a href="#sfinae-on-the-synthesized-function-object">SFINAE on the synthesized function object</a></li>
<li><a href="#no-handling-of-static-members">No handling of static members</a></li>
</ul></li>
<li><a href="#examples-and-use-cases">Examples and Use Cases</a><ul>
<li><a href="#polymorphic-value-types">Polymorphic Value Types</a></li>
<li><a href="#sum-types">Sum Types</a></li>
<li><a href="#dynamic-duck-typing">Dynamic Duck Typing</a></li>
<li><a href="#expression-templates">Expression Templates</a></li>
<li><a href="#dynamic-properties-reflection-extension">Dynamic Properties (reflection extension)</a></li>
<li><a href="#remote-procedure-calls-with-automatic-marshalling-reflection-extension">Remote Procedure Calls with automatic marshalling (reflection extension)</a></li>
<li><a href="#vector-of-values">Vector of values</a></li>
<li><a href="#asynchronous-proxy">Asynchronous proxy</a></li>
</ul></li>
<li><a href="#acknowledgements">Acknowledgements</a></li>
</ul>
</div>

</div>

<div id="body">
<h2 id="introduction"><a href="#introduction">Introduction</a></h2>
<p>This proposal suggests an approach to allow overloading the dot operator that is an alternative to the solution proposed in <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4477.pdf">N4477</a>. It is based on <strong>having the compiler synthesize a function object</strong> whenever a call to that operator is made rather than return a user-defined reference.</p>
<p>This approach can do everything that <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4477.pdf">N4477</a> can while avoiding some of its issues. The approach also allows some novel uses which are described below.</p>
<p>A simulated implementation as well as the various use cases presented in the proposal are also available as source code on github: <a href="https://github.com/mgaunard/operator-dot">https://github.com/mgaunard/operator-dot</a>.</p>
<h2 id="changelog"><a href="#changelog">Changelog</a></h2>
<h3 id="p0060r0---2015-09-18"><a href="#p0060r0---2015-09-18">P0060R0 - 2015-09-18</a></h3>
<ul>
<li>Changed arguments to member functions to be passed to the <code>operator.</code> overload and then forwarded to the synthesized function object instead of constructing a stateful function object, which simplifies the design and also makes it more flexible.</li>
<li>Added RPC with marshalling use case example</li>
<li>Added asynchronous proxy use case example</li>
</ul>
<h3 id="n4495---2015-05-22"><a href="#n4495---2015-05-22">N4495 - 2015-05-22</a></h3>
<ul>
<li>Initial version</li>
</ul>
<h2 id="motivation"><a href="#motivation">Motivation</a></h2>
<p>The advent of smart pointers, types making use of the capacity to overload the arrow (<code>-&gt;</code>) operator to mimic pointers while providing extra behaviour like automatic lifetime management, has only highlighted the lack of having the ability to overload the dot (<code>.</code>) operator to achieve smart references, or better yet, smart objects.</p>
<p>In the following listing, we will use the terminology <em>smart reference</em> to refer to a use case that is possible with both this proposal and <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4477.pdf">N4477</a>, and <em>smart object</em> for a use case that requires the method presented in this proposal.</p>
<p>Examples of <em>smart references</em> include:</p>
<ul>
<li><strong>Smart pointers that are really references</strong>: smart pointer-like objects that have reference semantics rather than pointer semantics.</li>
<li><strong>Proxies</strong>: objects that must intercept every call to a member before rerouting it to some other object.</li>
<li><strong>Interface refinement</strong>: build new objects by composing existing objects, forwarding to them, and adding new members.</li>
<li><strong>Pimpl and handles</strong>: making an indirection to another private object transparent without having to forward every member value or function.</li>
</ul>
<p>Examples of <em>smart objects</em> include:</p>
<ul>
<li><strong>Sum types aka variants</strong>: objects that can hold values of different types. It is possible to define operator dot so that it forwards to the members of the actual type contained.</li>
<li><strong>Duck typing</strong>: similar to sum types, but the error of not having a particular member function for a given type is delayed to when the binding to the actual value occurs.</li>
<li><strong>Expression templates and DSELs</strong>: building a type that allows delayed evaluation by building an object representing the call rather than evaluating it is very useful to build <em>Domain-Specific Embedded Languages</em> that are based on the famous expression templates technique.</li>
<li><strong>Aggregates of key-value pairs</strong>: objects that are aggregates of runtime-defined properties could be accessed through operator dot instead of an explicit string.</li>
<li><strong>Remote Procedure Calls</strong>: an object with member functions that transparently get translated to a request/response messaging system to call the function on a remote or distributed service.</li>
<li><strong>Repeated evaluation</strong>: objects that do not forward the member access to a single object but to several objects in succession.</li>
<li><strong>Asynchronous objects</strong>: object proxies which transform each member function call into an asynchronous call returning a future.</li>
</ul>
<p>Additionally, the function object approach allows fine control of what is forwarded, under what condition, and in what order. The discussion below provides more details.</p>
<h2 id="design-and-specification"><a href="#design-and-specification">Design and Specification</a></h2>
<h3 id="lookup-rules"><a href="#lookup-rules">Lookup rules</a></h3>
<p>When looking up a non-static member of a user-defined-type, if no member by the name requested exists, and the type has a declaration of a non-static member function named <code>operator.</code> with matching cv-qualifiers, then the compiler shall synthesize a function object with a <code>operator()</code> member function template taking an arbitrary object as parameter and applying the name to it. An instance of that synthesized function object is passsed as argument to the <code>operator.</code> member function.</p>
<p>For example, <code>x.some_name;</code> gets translated into <code>x.operator.(synthesized_function_type{});</code> where <code>x.some_name</code> wouldn't otherwise be found.</p>
<p>In this case, the synthesized function type could be equivalent to the following:</p>
<pre><code>struct synthesized_function_type {
    template&lt;class T&gt;
    auto operator()(T&amp;&amp; t) -&gt; decltype(t.some_name) noexcept(t.some_name) {
        return t.some_name;
    }
};</code></pre>
<p>Special capture behavior for calls to member functions is decribed in the next section.</p>
<h3 id="member-functions-and-scope-capture"><a href="#member-functions-and-scope-capture">Member functions and scope capture</a></h3>
<p>If the compiler must synthesize a function object for a member function call, each subexpression evaluating each argument shall be passed along as a template-parameter-pack to the <code>operator.</code> overload, which may then forward those arguments to the synthesized function object.</p>
<p>For example, the calls <code>x.some_name(a, foo(), foo())</code> shall get translated to to <code>x.operator.(synthesized_function_type(), a, foo(), foo());</code> where the synthesized function type could be equivalent to the following:</p>
<pre><code>struct synthesized_function_type {
    template&lt;class T, class... Args&gt;
    auto operator()(T&amp;&amp; t, Args&amp;&amp;... args) -&gt; decltype(t.some_name(std::forward&lt;Args&gt;(args)...)) noexcept(t.some_name(std::forward&lt;Args&gt;(args)...)) {
        return t.some_name(std::forward&lt;Args&gt;(args)...);
    }
};</code></pre>
<h3 id="extension-to-reflection"><a href="#extension-to-reflection">Extension to reflection</a></h3>
<p>The mechanism could optionally be extended to support <strong>reflection</strong> by adding arbitrary extra information within the synthesized function object type.</p>
<p>Further work will be done in that area in future versions of the proposal depending on feedback.</p>
<p>For example for member variables:</p>
<pre><code>struct synthesized_function_type {
    template&lt;class T&gt;
    auto operator()(T&amp;&amp; t) -&gt; decltype((t.some_name)) noexcept((t.some_name)) {
        return t.some_name;
    }

    static constexpr const char* name() { return &quot;some_name&quot;; }
    static constexpr bool is_member_function = false;
};</code></pre>
<p>For member functions:</p>
<pre><code>struct synthesized_function_type {
    template&lt;class T, class... Args&gt;
    auto operator()(T&amp;&amp; t, Args&amp;&amp;... args) -&gt; decltype(t.some_name(std::forward&lt;Args&gt;(args)...)) noexcept(t.some_name(std::forward&lt;Args&gt;(args)...)) {
        return t.some_name(std::forward&lt;Args&gt;(args)...);
    }

    static constexpr const char* name() { return &quot;some_name&quot;; }
    static constexpr bool is_member_function = true;
};</code></pre>
<h2 id="properties-of-the-design"><a href="#properties-of-the-design">Properties of the Design</a></h2>
<h3 id="controlling-reference-leaking"><a href="#controlling-reference-leaking">Controlling reference leaking</a></h3>
<p><a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4477.pdf">N4477</a> discusses <em>reference leaking</em> in section 5: the possibility that <code>operator.()</code> can result in functions accidentally returning a reference to an object held by a smart reference. Since N4477 proposes the implementation of <code>operator.()</code> in similar ways as <code>operator-&gt;()</code> but returning a reference rather than a pointer the control of the returned reference needs to be in the language.</p>
<p>When implementing <code>operator.()</code> in terms of a passed function object the implementer of a smart reference has full control over the type returned from <code>operator.()</code>. In its simplest form reference leaking can be prevented by not returning anything from the resulting operator:</p>
<pre><code>class strictly_non_leaking {
    X x;
public:
    template&lt;class Fun, class... Args&gt;
    auto operator.(Fun&amp;&amp; fun, Args&amp;&amp;... args) -&gt; void { fun(x, std::forward&lt;Args&gt;(args)...); }
};</code></pre>
<p>While that may be viable for some smart reference types, most smart reference would probably want to return a suitable result. It would be straight forward to prevent certain known return types, e.g., by conditionally wrapping results into a suitable type:</p>
<pre><code>class wrapping {
    X x;
public:
    wrapping(X&amp; ref);
    template&lt;class Fun, class... Args&gt;
    auto operator.(Fun&amp;&amp; fun, Args&amp;&amp;... args)
        -&gt; std::condition_t&lt;std::is_same_v&lt;X&amp;, decltype(fun(std::declval&lt;X&amp;&gt;(), std::forward&lt;Args&gt;(args)...))&gt;,
                            wrapping, decltype(fun(std::declval&lt;X&amp;&gt;(), std::forward&lt;Args&gt;(args)...))&gt; {
        return fun(x, std::forward&lt;Args&gt;(args)...);
    }
};</code></pre>
<p>What exactly a smart reference returns from a use can be controlled by the smart reference. In particular the good (<code>incr(x)</code>) case can be supported while the bad (<code>leak(x)</code>) case can be banned.</p>
<h3 id="overloading-operator.-on-multiple-objects"><a href="#overloading-operator.-on-multiple-objects">Overloading operator.() on multiple objects</a></h3>
<p><a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4477.pdf">N4477</a> discusses overloading <code>operator.()</code> in section 4.9. While there it is obvious that operator.() can be overloaded for cv-qualified version and reference qualifications, N4477 also proposes to overload on the reference type returned from <code>operator.()</code>. The idea is that multiple version of <code>operator.()</code> can be used to return different reference types and the unique version applicable for a member use is chosen. The choice of <code>operator.()</code> based on the reference type is similar to the choice made when finding a member function in a class with multiple base classes: if a unique match is found it is chosen otherwise (if there are no or multiple matches) the use is an error.</p>
<p>When passing a function object to <code>operator.()</code> this form of overloading isn't possible. However, such special overloading rules are not needed as the same effect can be achieved by determining if a function call can be made:</p>
<pre><code>class composite {
    A a;
    B b;
public:
    template class Fun, class... Args&gt;
    auto operator.(Fun&amp;&amp; fun, Args&amp;&amp;... args)
        -&gt; decltype(call_unique(std::bind(std::forward&lt;Fun&gt;(fun), std::forward&lt;Args&gt;(args)...), std::tie(this-&gt;a, this-&gt;b))) {
        return call_unique(std::bind(std::forward&lt;Fun&gt;(fun), std::forward&lt;Args&gt;(args)...), std::tie(this-&gt;a, this-&gt;b));
    }
};</code></pre>
<p>The function <code>call_unique()</code> determines if there is exactly one element <code>x</code> in the passed <code>std::tuple&lt;...&gt;</code> for which <code>fun(x)</code> is a valid called and, if so, returns the result of calling <code>fun</code> with this element. Otherwise, it produces an error. This function isn't easy to write but it could be made available by the standard library to aid with common choices. Since it is a library function other choices could be made, however. For example, instead of calling the unique choice a different approach could be to call the first match.</p>
<h3 id="sfinae-on-the-synthesized-function-object"><a href="#sfinae-on-the-synthesized-function-object">SFINAE on the synthesized function object</a></h3>
<p>A lot of advanced uses of overloading <code>operator.</code> with the scheme described on this proposal rely on SFINAE extended for expressions. SFINAE for expressions is necessary to be able to tell whether a member exists for a particular object, i.e., whether the synthesized function object can be called with a specific parameter type.</p>
<p>This is why the signature of the <code>operator()</code> member function template of the synthesized function objects has a return type defined with <code>decltype</code> rather than just relying on a specification using <code>auto</code> or <code>decltype(auto)</code>.</p>
<h3 id="no-handling-of-static-members"><a href="#no-handling-of-static-members">No handling of static members</a></h3>
<p>To build perfect smart references or proxies, it would not only be required to forward regular members, but static ones as well. For example, consider a proxy for <code>std::vector</code> which should have the <code>::iterator</code> be provided, too.</p>
<p>Like <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4477.pdf">N4477</a>, the proposal currently doesn't cover static members. The mechanism could be extended to support these members. The main issue is being able to deal with both types and values, in particular in contexts where member types are not annotated with <code>typename</code>.</p>
<h2 id="examples-and-use-cases"><a href="#examples-and-use-cases">Examples and Use Cases</a></h2>
<h3 id="polymorphic-value-types"><a href="#polymorphic-value-types">Polymorphic Value Types</a></h3>
<p>Inheritance and subtyping polymorphism is a use case for some sort of dynamic typing. If given a base class <code>Base</code>, and several derived classes <code>Derived1</code>, <code>Derived2</code> or <code>Derivedn</code>, it is often useful to be able to have an object that can contain any of the <code>Derivedi</code> classes derived from <code>Base</code>.</p>
<p>Smart pointers are a popular solutions to this problem. While smart pointers provide an entity semantic, there is also an argument that can be made for having value semantics instead, where copies actually copies the data instead of aliasing it.</p>
<p>This copying can be achieved using a special smart pointer. There are several implementations of this approach on the Internet under the name <code>clone_ptr</code>. Pointer syntax is however not very appropriate when providing someting using value semantics. Here is an example of what it could look like with this proposal. Let's name the type that can hold any type derived from <code>T</code> while providing a value semantic <code>poly&lt;T&gt;</code>, below is a simplistic implementation relying on an intrusive &quot;clone&quot; virtual member function and lacking move semantics and other fancy features.</p>
<pre><code>template&lt;class T&gt;
struct poly {
    poly(T const&amp; t) : ptr(new T(t)) {}
    ~poly() { delete ptr; }

    poly(const poly&amp; other) ptr(other.p-&gt;clone()) {}

    poly&amp; operator=(poly other) {
        std::swap(ptr, other.ptr);
        return *this;
    }

    template&lt;class F, class... Args&gt;
    auto operator.(F f, Args&amp;&amp;... args) -&gt; decltype(f(std::declval&lt;T&amp;&gt;(), std::forward&lt;Args&gt;(args)...))
        return f(*ptr, std::forward&lt;Args&gt;(args)...);
    }

    template&lt;class F, class... Args&gt;
    auto operator.(F f, Args&amp;&amp;... args) const -&gt; decltype(f(std::declval&lt;T const&amp;&gt;(), std::forward&lt;Args&gt;(args)...))
        return f(static_cast&lt;T const&amp;&gt;(*ptr), std::forward&lt;Args&gt;(args)...);
    }

private:
    T* ptr;
};</code></pre>
<p>It then becomes possible to write things like this:</p>
<pre><code>poly&lt;Base&gt; obj = Derived1();
a.virtual_member_function_of_Base();
a = Derived2();
int x = a.member_variable_of_Base;</code></pre>
<h3 id="sum-types"><a href="#sum-types">Sum Types</a></h3>
<p>Sum types, also called tagged unions or variants, are data structures that can hold one object out of a list of possibly unrelated types at a time. Proposal <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4450.pdf">N4450</a> suggests adding such a type to the standard library, named <code>variant</code>, based on the <code>boost::variant</code> class template.</p>
<p>Proposal <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4450.pdf">N4450</a> for the variant type provides very limited operator overloading (only <code>&lt;</code>, <code>&lt;=</code>, <code>=</code>, <code>!=</code>, <code>&gt;=</code> and <code>&gt;</code>), but a case could be made for providing overloading for all operators, including operator dot. This raises a couple of interesting questions regarding what the result type of that operator should be, and whether a hard error should be emitted if the operator in question is not available on one or more of the types in the set.</p>
<p>For the use case below, we present a partial interface of a simple variant implementation with freestore-based storage and pseudo-code to ignore some of the implementation complications inherent to variant. Operator dot returns the common type of all possible cases, and the operator being called must be valid for all cases.</p>
<pre><code>template&lt;class... T&gt;
struct variant {
    template&lt;class U&gt;
    variant(U const&amp; u) : ptr(new U(u)), which(find_offset&lt;seq&lt;T...&gt;, U&gt;::value) {}

    ~variant() { type_erased_delete(ptr); }

    variant(variant const&amp; other) : ptr(type_erased_clone(other)), which(other.which) {}

    variant&amp; operator=(variant other) {
        swap(ptr, other.ptr);
        swap(which, other.which);
        return *this;
    }
    
    // collapse_result_of ensures the overload is only valid if all cases return the same type
    template&lt;class F, class... Args&gt;
    auto operator.(F f, Args&amp;&amp;... args) -&gt; typename collapse_result_of&lt;F(Args...), T...&gt;::type {
        switch(which)
        {
            case 0: return f(*static_cast&lt;T0*&gt;(ptr), std::forward&lt;Args&gt;(args)...);
            case 1: return f(*static_cast&lt;T1*&gt;(ptr), std::forward&lt;Args&gt;(args)...);
            /* for every Ti... */
        }
    }

    template&lt;class F, class... Args&gt;
    auto operator.(F f, Args&amp;&amp;... args) const -&gt; -&gt; typename collapse_result_of&lt;F(Args...), T...&gt;::type {
        switch(which)
        {
            case 0: return f(*static_cast&lt;T0 const*&gt;(ptr), std::forward&lt;Args&gt;(args)...);
            case 1: return f(*static_cast&lt;T1 const*&gt;(ptr), std::forward&lt;Args&gt;(args)...);
            /* for every Ti... */
        }
    }

private:
    void* ptr;
    int which;
};</code></pre>
<p>With the <code>collapse_result_of</code> meta-function defined as such:</p>
<pre><code>template&lt;class Sig, class... Types&gt;
struct collapse_result_of;

template&lt;class F, class... Args, class Type&gt;
struct collapse_result_of&lt;F(Args...), Type&gt;
     : std::result_of&lt;F(Type, Args...)&gt;
{};

template&lt;class F, class... Args, class Type, class... Types&gt;
struct collapse_result_of&lt;F(Args...), Type, Types...&gt;
     : collapse_result_of&lt;F(Args...), Types...&gt;
     , std::result_of&lt;F(Type, Args...)&gt;
{};</code></pre>
<p>This use case is a prime example of a smart object. This interface can be achieved by synthesizing a function object but it cannot be achieved by forwarding to a reference like in N4477 (operator dot), since there is no reference to a single object that variant could return.</p>
<p>It becomes possible to write things like this:</p>
<pre><code>struct Foo { const char* name() { return &quot;Foo&quot;; } };
struct Bar { const char* name() { return &quot;Bar&quot;; } void bark() { cout &lt;&lt; name() &lt;&lt; endl; } };

variant&lt;Foo, Bar&gt; v = Foo();
v = Bar();
const char* s = v.name();
//v.bark(); // error: not all types define &#39;bark&#39;</code></pre>
<h3 id="dynamic-duck-typing"><a href="#dynamic-duck-typing">Dynamic Duck Typing</a></h3>
<p>Duck typing is a technique which involves binding a name to an object as lately as possible: if the name is available at the time it is needed, call it, otherwise raise an error. Most dynamic typed language are based on this principle as it provides a very easy and flexible programming model.</p>
<p>It cannot be implemented in C++ generally, but it is possible to provide duck typing over a finite set of types, so it is possible to provide it for a variant type like above. It requires being able to test at compile-time if a given type satisfies the call, in order to be able to fallback to code that generates an error in case the expression is not supported.</p>
<p>This is one use case that requires the synthesized function object to contain its full body in its signature, so that it can be used in SFINAE contexts.</p>
<p>From a synthesized function object for the operator dot call, the implementation would wrap it in another function object with a fallback by doing something like this:</p>
<pre><code>template&lt;class T, class R = void&gt;
struct sink { typedef R type; };

template&lt;class Sig, class Enable = void&gt;
struct is_callable : std::false_type {};

template&lt;class F, class... Args&gt;
struct is_callable&lt;F(Args...), typename sink&lt;decltype(std::declval&lt;F&gt;()(std::declval&lt;Args&gt;()...))&gt;::type&gt; : std::true_type {};

template&lt;class F, class R&gt;
struct call_or_throw : F {
    using F::operator();

    template&lt;class T, class... Args&gt;
    typename std::enable_if&lt;!is_callable&lt;F(T&amp;&amp;, Args&amp;&amp;...)&gt;::value, R&gt;::type operator()(T&amp;&amp; t, Args&amp;&amp;...) const
    {
        throw std::runtime_error(&quot;No such operation&quot;);
    }
};</code></pre>
<p>The <code>operator.</code> overload now looks like this:</p>
<pre><code>template&lt;class... T&gt;
struct duck_variant {
    /* content from variant... */
    
    // require all valid cases to return the same type
    template&lt;class F, class... Args&gt;
    auto operator.(F f, Args&amp;&amp;... args) -&gt; typename collapse_result_of&lt;F(Args&amp;&amp;...), T...&gt;::type {
    
        typedef typename collapse_result_of&lt;F(Args&amp;&amp;...), T...&gt;::type R;
        
        switch(which)
        {
            case 0: return call_or_throw&lt;F, R&gt;{f}(*static_cast&lt;T0*&gt;(ptr), std::forward&lt;Args&gt;(args)...);
            case 1: return call_or_throw&lt;F, R&gt;{f}(*static_cast&lt;T1*&gt;(ptr), std::forward&lt;Args&gt;(args)...);
            /* for every Ti... */
        }
    }
};</code></pre>
<p>It becomes possible to write things like this:</p>
<pre><code>struct Foo { const char* name() { return &quot;Foo&quot;; } };
struct Bar { const char* name() { return &quot;Bar&quot;; } void bark() { cout &lt;&lt; name() &lt;&lt; endl; } };

duck_variant&lt;Foo, Bar&gt; v = Foo();
v = Bar();
const char* s = v.name();
v.bark(); // correct even if Foo has no &#39;bark&#39;</code></pre>
<h3 id="expression-templates"><a href="#expression-templates">Expression Templates</a></h3>
<p>Expression templates is a mechanism using operator overloading to delay evaluations of expressions and then evaluate them with a given context, which enables building entire Domain-Specific Languages embedded into C++. For this use case, forwarding to a reference is not possible, and generating a function object fits exactly the needs of delaying evaluation that is needed.</p>
<p>In this case, the <code>operator.</code> would just return the synthesized function object or more likely a wrapper of that function object.</p>
<h3 id="dynamic-properties-reflection-extension"><a href="#dynamic-properties-reflection-extension">Dynamic Properties (reflection extension)</a></h3>
<p>Another use case where overloading the dot operator is useful is for objects where the member names are dynamic, like those obtained from binding to a dynamic language, serialization to XML or JSON, or anything deciding fields at runtime. This cannot be addressed by just providing a function object, but it is trivial to extend the function objects to contain additional information to support that use case. With N4477 (operator dot), there is no obvious way to extend the mechanism to support this use case.</p>
<p>Assuming the synthesized function object is augmented to support reflection, i.e., a <code>name()</code> function return the name of the member being applied, it could therefore look like this:</p>
<pre><code>struct Value {
    Value() : data(Map()) {}
    Value(int i) : data(i) {}
    Value(double d) : data(d) {}
    Value(std::string const&amp; s) : data(s) {}

    template&lt;class F&gt;
    Value&amp; operator.(F f) {
        return get&lt;Map&gt;(data)[F::name()];
    }

    template&lt;class F&gt;
    Value const&amp; operator.(F f) const {
        return get&lt;Map&gt;(data)[F::name()];
    }

private:
    typedef std::unordered_map&lt;std::string, Value&gt; Map;
    variant&lt;Map, int, double, std::string&gt; data;
}</code></pre>
<p>And this would allow the following usage:</p>
<pre><code>Value v;
v.foo = 42;
v.bar = &quot;bar&quot;;</code></pre>
<p>Adding &quot;foo&quot; and &quot;bar&quot; members dynamically.</p>
<h3 id="remote-procedure-calls-with-automatic-marshalling-reflection-extension"><a href="#remote-procedure-calls-with-automatic-marshalling-reflection-extension">Remote Procedure Calls with automatic marshalling (reflection extension)</a></h3>
<p>With Service-Oriented Architectures and distributed systems becoming increasingly popular, it is often necessary to call a function on a remote machine, after having serialized the arguments to the function, and then deserializing the result.</p>
<p>The existing bindings for such frameworks in C++ are significantly more verbose than their equivalent in dynamic languages, and overloading <code>operator.</code> could allow to simplify them a lot.</p>
<pre><code>struct my_service {
    template&lt;class F, class... Args&gt;
    Value operator.(F f, Args&amp;&amp;... args) {
        std::vector&lt;Value&gt; value_args = { Value(args)... };
        return send_request(F::name(), value_args);
    }

private:
    // serialize `function_name&#39; and `args&#39; to message
    // send request message to service
    // get response message from service
    // deserialize it to Value
    Value send_request(const char* function_name, std::vector&lt;Value&gt; const&amp; args);
};</code></pre>
<p>Then an object could be used like this:</p>
<pre><code>news_service.latest_news(&quot;John Doe&quot;, 100);</code></pre>
<p>which could transparently generate a JSON-RPC request &quot;latest_news&quot; to a news service to get the 100 latest news about John Doe.</p>
<h3 id="vector-of-values"><a href="#vector-of-values">Vector of values</a></h3>
<p>Just like <code>+</code> on <code>std::valarray</code> adds all of its values, it could also be interesting to call a member on all the values of the vector as well. Consider <code>valarray&lt; complex&lt;T&gt; &gt;</code>, it would be useful to be able to apply <code>.real()</code> and <code>.imag()</code> to all members of the vector at once without requiring special specialization.</p>
<p>This is a use case that requires calling the function object several times on different values, and that isn't supported by forwarding it to a single reference like in <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4477.pdf">N4477</a>.</p>
<pre><code>template&lt;class T&gt;
struct array {
    template&lt;class F, class... Args&gt;
    auto operator.(F f, Args&amp;&amp;... args) -&gt; array&lt; decltype(f(values[0], std::forward&lt;Args&gt;(args)..)) &gt; {
        array&lt; decltype(f(values[0], std::forward&lt;Args&gt;(args)...)) &gt; result(values.size());
        for(size_t i=0; i&lt;values.size(); ++i)
            result[i] = f(values[i]);
        }
        return result;
    }

private:
    std::vector&lt;T&gt; values;
};</code></pre>
<p>which would then be used to do the following:</p>
<pre><code>std::valarray&lt; std::complex&lt;float&gt; &gt; complex_numbers;
std::valarray&lt; float &gt; real_part = complex_numbers.real();
std::valarray&lt; float &gt; imaginary_part = complex_numbers.imag();</code></pre>
<h3 id="asynchronous-proxy"><a href="#asynchronous-proxy">Asynchronous proxy</a></h3>
<p>A normal object runs each of its function synchronously; it can however be interesting to provide an object adaptor that makes all those member functions run asynchronously by returning a future to their result instead.</p>
<p>Additionally, if an argument to a member function to an asynchronous object is itself a future, it can add the argument as a dependency to the new asynchronous call instead of waiting for the argument to be available.</p>
<p>All of this can be done generically and transparently by overloading <code>operator.</code>.</p>
<pre><code>template&lt;class T&gt;
struct async_obj {
    template&lt;class... Args&gt;
    async_obj(Args&amp;&amp;...) : obj(std::forward&lt;Args&gt;(args)...) {}

    template&lt;class F, class... Args&gt;
    auto operator.(F f, Args&amp;&amp;... args) -&gt; std::future&lt; decltype(f(std::declval&lt;T&amp;&gt;(), std::forward&lt;Args&gt;(args)...)) &gt; {
        return is_future&lt;Args...&gt; ? 
               std::when_all(wrap(obj), wrap(std::forward&lt;Args&gt;(args))...).then(f) :
               std::async(f, obj, std::forward&lt;Args&gt;(args)...);
    }

private:
    T obj;
};</code></pre>
<p>with the following implementation details to convert arguments back and forth between futures:</p>
<pre><code>template&lt;class T&gt;
T&amp;&amp; unwrap(T&amp;&amp;) { return t; }
template&lt;class T&gt;
T unwrap(future&lt;T&gt;&amp;&amp;) { return t.get(); }
template&lt;class T&gt;
using unwrap_t = decltype(unwrap(std::declval&lt;T&gt;()));

template&lt;class T&gt;
future&lt;T&gt; wrap(T&amp;&amp; t) { return std::make_ready_future&lt;T&gt;(t); }
template&lt;class T&gt;
future&lt;T&gt;&amp;&amp; wrap(future&lt;T&gt;&amp;&amp; t) { return t; }

template&lt;class... T&gt;
bool is_future = !std::is_same&lt;T, unwrap_t&lt;T&gt; &gt; || ... ; // fold expression</code></pre>
<p>then given a user-defined object like this:</p>
<pre><code>struct my_object
{
    double compute_approximation(double value);
    double compute_solution(double value, double approximation);
};</code></pre>
<p>You could obtain something like so:</p>
<pre><code>async_obj&lt;my_object&gt; obj;
std::future&lt;double&gt; approx = obj.compute_approximation(42.);
std::future&lt;double&gt; sol = obj.compute_solution(42., approx);</code></pre>
<p>this code doesn't block and automatically builds a data flow between <code>compute_approximation</code> and <code>compute_solution</code>.</p>
<h2 id="acknowledgements"><a href="#acknowledgements">Acknowledgements</a></h2>
<ul>
<li>Thanks to <a href="unmobile@gmail.com">Phil Miller</a> for having inspired the RPC use case.</li>
<li>Thanks to <a href="gpderetta@gmail.com">Giovanni Piero Deretta</a> for providing the asynchronous proxy use case.</li>
</ul>
</div>

</body>
</html>