<!doctype html><html lang="en">
 <head>
  <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  <meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
  <title>p0834r0: Lifting overload sets into objects</title>
<style data-fill-with="stylesheet">/******************************************************************************
 *                   Style sheet for the W3C specifications                   *
 *
 * Special classes handled by this style sheet include:
 *
 * Indices
 *   - .toc for the Table of Contents (<ol class="toc">)
 *     + <span class="secno"> for the section numbers
 *   - #toc for the Table of Contents (<nav id="toc">)
 *   - ul.index for Indices (<a href="#ref">term</a><span>, in §N.M</span>)
 *   - table.index for Index Tables (e.g. for properties or elements)
 *
 * Structural Markup
 *   - table.data for general data tables
 *     -> use 'scope' attribute, <colgroup>, <thead>, and <tbody> for best results !
 *     -> use <table class='complex data'> for extra-complex tables
 *     -> use <td class='long'> for paragraph-length cell content
 *     -> use <td class='pre'> when manual line breaks/indentation would help readability
 *   - dl.switch for switch statements
 *   - ol.algorithm for algorithms (helps to visualize nesting)
 *   - .figure and .caption (HTML4) and figure and figcaption (HTML5)
 *     -> .sidefigure for right-floated figures
 *   - ins/del
 *
 * Code
 *   - pre and code
 *
 * Special Sections
 *   - .note       for informative notes             (div, p, span, aside, details)
 *   - .example    for informative examples          (div, p, pre, span)
 *   - .issue      for issues                        (div, p, span)
 *   - .assertion  for assertions                    (div, p, span)
 *   - .advisement for loud normative statements     (div, p, strong)
 *   - .annoying-warning for spec obsoletion notices (div, aside, details)
 *
 * Definition Boxes
 *   - pre.def   for WebIDL definitions
 *   - table.def for tables that define other entities (e.g. CSS properties)
 *   - dl.def    for definition lists that define other entitles (e.g. HTML elements)
 *
 * Numbering
 *   - .secno for section numbers in .toc and headings (<span class='secno'>3.2</span>)
 *   - .marker for source-inserted example/figure/issue numbers (<span class='marker'>Issue 4</span>)
 *   - ::before styled for CSS-generated issue/example/figure numbers:
 *     -> Documents wishing to use this only need to add
 *        figcaption::before,
 *        .caption::before { content: "Figure "  counter(figure) " ";  }
 *        .example::before { content: "Example " counter(example) " "; }
 *        .issue::before   { content: "Issue "   counter(issue) " ";   }
 *
 * Header Stuff (ignore, just don't conflict with these classes)
 *   - .head for the header
 *   - .copyright for the copyright
 *
 * Miscellaneous
 *   - .overlarge for things that should be as wide as possible, even if
 *     that overflows the body text area. This can be used on an item or
 *     on its container, depending on the effect desired.
 *     Note that this styling basically doesn't help at all when printing,
 *     since A4 paper isn't much wider than the max-width here.
 *     It's better to design things to fit into a narrower measure if possible.
 *   - js-added ToC jump links (see fixup.js)
 *
 ******************************************************************************/

/******************************************************************************/
/*                                   Body                                     */
/******************************************************************************/

	body {
		counter-reset: example figure issue;

		/* Layout */
		max-width: 50em;               /* limit line length to 50em for readability   */
		margin: 0 auto;                /* center text within page                     */
		padding: 1.6em 1.5em 2em 50px; /* assume 16px font size for downlevel clients */
		padding: 1.6em 1.5em 2em calc(26px + 1.5em); /* leave space for status flag     */

		/* Typography */
		line-height: 1.5;
		font-family: sans-serif;
		widows: 2;
		orphans: 2;
		word-wrap: break-word;
		overflow-wrap: break-word;
		hyphens: auto;

		/* Colors */
		color: black;
		background: white top left fixed no-repeat;
		background-size: 25px auto;
	}


/******************************************************************************/
/*                         Front Matter & Navigation                          */
/******************************************************************************/

/** Header ********************************************************************/

	div.head { margin-bottom: 1em }
	div.head hr { border-style: solid; }

	div.head h1 {
		font-weight: bold;
		margin: 0 0 .1em;
		font-size: 220%;
	}

	div.head h2 { margin-bottom: 1.5em;}

/** W3C Logo ******************************************************************/

	.head .logo {
		float: right;
		margin: 0.4rem 0 0.2rem .4rem;
	}

	.head img[src*="logos/W3C"] {
		display: block;
		border: solid #1a5e9a;
		border-width: .65rem .7rem .6rem;
		border-radius: .4rem;
		background: #1a5e9a;
		color: white;
		font-weight: bold;
	}

	.head a:hover > img[src*="logos/W3C"],
	.head a:focus > img[src*="logos/W3C"] {
		opacity: .8;
	}

	.head a:active > img[src*="logos/W3C"] {
		background: #c00;
		border-color: #c00;
	}

	/* see also additional rules in Link Styling section */

/** Copyright *****************************************************************/

	p.copyright,
	p.copyright small { font-size: small }

/** Back to Top / ToC Toggle **************************************************/

	@media print {
		#toc-nav {
			display: none;
		}
	}
	@media not print {
		#toc-nav {
			position: fixed;
			z-index: 2;
			bottom: 0; left: 0;
			margin: 0;
			min-width: 1.33em;
			border-top-right-radius: 2rem;
			box-shadow: 0 0 2px;
			font-size: 1.5em;
			color: black;
		}
		#toc-nav > a {
			display: block;
			white-space: nowrap;

			height: 1.33em;
			padding: .1em 0.3em;
			margin: 0;

			background: white;
			box-shadow: 0 0 2px;
			border: none;
			border-top-right-radius: 1.33em;
			background: white;
		}
		#toc-nav > #toc-jump {
			padding-bottom: 2em;
			margin-bottom: -1.9em;
		}

		#toc-nav > a:hover,
		#toc-nav > a:focus {
			background: #f8f8f8;
		}
		#toc-nav > a:not(:hover):not(:focus) {
			color: #707070;
		}

		/* statusbar gets in the way on keyboard focus; remove once browsers fix */
		#toc-nav > a[href="#toc"]:not(:hover):focus:last-child {
			padding-bottom: 1.5rem;
		}

		#toc-nav:not(:hover) > a:not(:focus) > span + span {
			/* Ideally this uses :focus-within on #toc-nav */
			display: none;
		}
		#toc-nav > a > span + span {
			padding-right: 0.2em;
		}

		#toc-toggle-inline {
			vertical-align: 0.05em;
			font-size: 80%;
			color: gray;
			color: hsla(203,20%,40%,.7);
			border-style: none;
			background: transparent;
			position: relative;
		}
		#toc-toggle-inline:hover:not(:active),
		#toc-toggle-inline:focus:not(:active) {
			text-shadow: 1px 1px silver;
			top: -1px;
			left: -1px;
		}

		#toc-nav :active {
			color: #C00;
		}
	}

/** ToC Sidebar ***************************************************************/

	/* Floating sidebar */
	@media screen {
		body.toc-sidebar #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			max-width: 80%;
			max-width: calc(100% - 2em - 26px);
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			background: inherit;
			background-color: #f7f8f9;
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
		}
		body.toc-sidebar #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
		}
		body.toc-sidebar #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	/* Hide main scroller when only the ToC is visible anyway */
	@media screen and (max-width: 28em) {
		body.toc-sidebar {
			overflow: hidden;
		}
	}

	/* Sidebar with its own space */
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			background: inherit;
			background-color: #f7f8f9;
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
		}
		body:not(.toc-inline) #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
		}

		body:not(.toc-inline) {
			padding-left: 29em;
		}
		/* See also Overflow section at the bottom */

		body:not(.toc-inline) #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) {
			margin: 0 4em;
		}
	}

/******************************************************************************/
/*                                Sectioning                                  */
/******************************************************************************/

/** Headings ******************************************************************/

	h1, h2, h3, h4, h5, h6, dt {
		page-break-after: avoid;
		page-break-inside: avoid;
		font: 100% sans-serif;   /* Reset all font styling to clear out UA styles */
		font-family: inherit;    /* Inherit the font family. */
		line-height: 1.2;        /* Keep wrapped headings compact */
		hyphens: manual;         /* Hyphenated headings look weird */
	}

	h2, h3, h4, h5, h6 {
		margin-top: 3rem;
	}

	h1, h2, h3 {
		color: #005A9C;
		background: transparent;
	}

	h1 { font-size: 170%; }
	h2 { font-size: 140%; }
	h3 { font-size: 120%; }
	h4 { font-weight: bold; }
	h5 { font-style: italic; }
	h6 { font-variant: small-caps; }
	dt { font-weight: bold; }

/** Subheadings ***************************************************************/

	h1 + h2,
	#subtitle {
		/* #subtitle is a subtitle in an H2 under the H1 */
		margin-top: 0;
	}
	h2 + h3,
	h3 + h4,
	h4 + h5,
	h5 + h6 {
		margin-top: 1.2em; /* = 1 x line-height */
	}

/** Section divider ***********************************************************/

	:not(.head) > hr {
		font-size: 1.5em;
		text-align: center;
		margin: 1em auto;
		height: auto;
		border: transparent solid 0;
		background: transparent;
	}
	:not(.head) > hr::before {
		content: "\2727\2003\2003\2727\2003\2003\2727";
	}

/******************************************************************************/
/*                            Paragraphs and Lists                            */
/******************************************************************************/

	p {
		margin: 1em 0;
	}

	dd > p:first-child,
	li > p:first-child {
		margin-top: 0;
	}

	ul, ol {
		margin-left: 0;
		padding-left: 2em;
	}

	li {
		margin: 0.25em 0 0.5em;
		padding: 0;
	}

	dl dd {
		margin: 0 0 .5em 2em;
	}

	.head dd + dd { /* compact for header */
		margin-top: -.5em;
	}

	/* Style for algorithms */
	ol.algorithm ol:not(.algorithm),
	.algorithm > ol ol:not(.algorithm) {
	 border-left: 0.5em solid #DEF;
	}

	/* Put nice boxes around each algorithm. */
	[data-algorithm]:not(.heading) {
	  padding: .5em;
	  border: thin solid #ddd; border-radius: .5em;
	  margin: .5em calc(-0.5em - 1px);
	}
	[data-algorithm]:not(.heading) > :first-child {
	  margin-top: 0;
	}
	[data-algorithm]:not(.heading) > :last-child {
	  margin-bottom: 0;
	}

	/* Style for switch/case <dl>s */
	dl.switch > dd > ol.only,
	dl.switch > dd > .only > ol {
	 margin-left: 0;
	}
	dl.switch > dd > ol.algorithm,
	dl.switch > dd > .algorithm > ol {
	 margin-left: -2em;
	}
	dl.switch {
	 padding-left: 2em;
	}
	dl.switch > dt {
	 text-indent: -1.5em;
	 margin-top: 1em;
	}
	dl.switch > dt + dt {
	 margin-top: 0;
	}
	dl.switch > dt::before {
	 content: '\21AA';
	 padding: 0 0.5em 0 0;
	 display: inline-block;
	 width: 1em;
	 text-align: right;
	 line-height: 0.5em;
	}

/** Terminology Markup ********************************************************/


/******************************************************************************/
/*                                 Inline Markup                              */
/******************************************************************************/

/** Terminology Markup ********************************************************/
	dfn   { /* Defining instance */
		font-weight: bolder;
	}
	a > i { /* Instance of term */
		font-style: normal;
	}
	dt dfn code, code.idl {
		font-size: medium;
	}
	dfn var {
		font-style: normal;
	}

/** Change Marking ************************************************************/

	del { color: red;  text-decoration: line-through; }
	ins { color: #080; text-decoration: underline;    }

/** Miscellaneous improvements to inline formatting ***************************/

	sup {
		vertical-align: super;
		font-size: 80%
	}

/******************************************************************************/
/*                                    Code                                    */
/******************************************************************************/

/** General monospace/pre rules ***********************************************/

	pre, code, samp {
		font-family: Menlo, Consolas, "DejaVu Sans Mono", Monaco, monospace;
		font-size: .9em;
		page-break-inside: avoid;
		hyphens: none;
		text-transform: none;
	}
	pre code,
	code code {
		font-size: 100%;
	}

	pre {
		margin-top: 1em;
		margin-bottom: 1em;
		overflow: auto;
	}

/** Inline Code fragments *****************************************************/

  /* Do something nice. */

/******************************************************************************/
/*                                    Links                                   */
/******************************************************************************/

/** General Hyperlinks ********************************************************/

	/* We hyperlink a lot, so make it less intrusive */
	a[href] {
		color: #034575;
		text-decoration: none;
		border-bottom: 1px solid #707070;
		/* Need a bit of extending for it to look okay */
		padding: 0 1px 0;
		margin: 0 -1px 0;
	}
	a:visited {
		border-bottom-color: #BBB;
	}

	/* Use distinguishing colors when user is interacting with the link */
	a[href]:focus,
	a[href]:hover {
		background: #f8f8f8;
		background: rgba(75%, 75%, 75%, .25);
		border-bottom-width: 3px;
		margin-bottom: -2px;
	}
	a[href]:active {
		color: #C00;
		border-color: #C00;
	}

	/* Backout above styling for W3C logo */
	.head .logo,
	.head .logo a {
		border: none;
		text-decoration: none;
		background: transparent;
	}

/******************************************************************************/
/*                                    Images                                  */
/******************************************************************************/

	img {
		border-style: none;
	}

	/* For autogen numbers, add
	   .caption::before, figcaption::before { content: "Figure " counter(figure) ". "; }
	*/

	figure, .figure, .sidefigure {
		page-break-inside: avoid;
		text-align: center;
		margin: 2.5em 0;
	}
	.figure img,    .sidefigure img,    figure img,
	.figure object, .sidefigure object, figure object {
		max-width: 100%;
		margin: auto;
	}
	.figure pre, .sidefigure pre, figure pre {
		text-align: left;
		display: table;
		margin: 1em auto;
	}
	.figure table, figure table {
		margin: auto;
	}
	@media screen and (min-width: 20em) {
		.sidefigure {
			float: right;
			width: 50%;
			margin: 0 0 0.5em 0.5em
		}
	}
	.caption, figcaption, caption {
		font-style: italic;
		font-size: 90%;
	}
	.caption::before, figcaption::before, figcaption > .marker {
		font-weight: bold;
	}
	.caption, figcaption {
		counter-increment: figure;
	}

	/* DL list is indented 2em, but figure inside it is not */
	dd > .figure, dd > figure { margin-left: -2em }

/******************************************************************************/
/*                             Colored Boxes                                  */
/******************************************************************************/

	.issue, .note, .example, .assertion, .advisement, blockquote {
		padding: .5em;
		border: .5em;
		border-left-style: solid;
		page-break-inside: avoid;
	}
	span.issue, span.note {
		padding: .1em .5em .15em;
		border-right-style: solid;
	}

	.issue,
	.note,
	.example,
	.advisement,
	.assertion,
	blockquote {
		margin: 1em auto;
	}
	.note  > p:first-child,
	.issue > p:first-child,
	blockquote > :first-child {
		margin-top: 0;
	}
	blockquote > :last-child {
		margin-bottom: 0;
	}

/** Blockquotes ***************************************************************/

	blockquote {
		border-color: silver;
	}

/** Open issue ****************************************************************/

	.issue {
		border-color: #E05252;
		background: #FBE9E9;
		counter-increment: issue;
		overflow: auto;
	}
	.issue::before, .issue > .marker {
		text-transform: uppercase;
		color: #AE1E1E;
		padding-right: 1em;
		text-transform: uppercase;
	}
	/* Add .issue::before { content: "Issue " counter(issue) " "; } for autogen numbers,
	   or use class="marker" to mark up the issue number in source. */

/** Example *******************************************************************/

	.example {
		border-color: #E0CB52;
		background: #FCFAEE;
		counter-increment: example;
		overflow: auto;
		clear: both;
	}
	.example::before, .example > .marker {
		text-transform: uppercase;
		color: #827017;
		min-width: 7.5em;
		display: block;
	}
	/* Add .example::before { content: "Example " counter(example) " "; } for autogen numbers,
	   or use class="marker" to mark up the example number in source. */

/** Non-normative Note ********************************************************/

	.note {
		border-color: #52E052;
		background: #E9FBE9;
		overflow: auto;
	}

	.note::before, .note > .marker,
	details.note > summary::before,
	details.note > summary > .marker {
		text-transform: uppercase;
		display: block;
		color: hsl(120, 70%, 30%);
	}
	/* Add .note::before { content: "Note"; } for autogen label,
	   or use class="marker" to mark up the label in source. */

	details.note > summary {
		display: block;
		color: hsl(120, 70%, 30%);
	}
	details.note[open] > summary {
		border-bottom: 1px silver solid;
	}

/** Assertion Box *************************************************************/
	/*  for assertions in algorithms */

	.assertion {
		border-color: #AAA;
		background: #EEE;
	}

/** Advisement Box ************************************************************/
	/*  for attention-grabbing normative statements */

	.advisement {
		border-color: orange;
		border-style: none solid;
		background: #FFEECC;
	}
	strong.advisement {
		display: block;
		text-align: center;
	}
	.advisement > .marker {
		color: #B35F00;
	}

/** Spec Obsoletion Notice ****************************************************/
	/* obnoxious obsoletion notice for older/abandoned specs. */

	details {
		display: block;
	}
	summary {
		font-weight: bolder;
	}

	.annoying-warning:not(details),
	details.annoying-warning:not([open]) > summary,
	details.annoying-warning[open] {
		background: #fdd;
		color: red;
		font-weight: bold;
		padding: .75em 1em;
		border: thick red;
		border-style: solid;
		border-radius: 1em;
	}
	.annoying-warning :last-child {
		margin-bottom: 0;
	}

@media not print {
	details.annoying-warning[open] {
		position: fixed;
		left: 1em;
		right: 1em;
		bottom: 1em;
		z-index: 1000;
	}
}

	details.annoying-warning:not([open]) > summary {
		text-align: center;
	}

/** Entity Definition Boxes ***************************************************/

	.def {
		padding: .5em 1em;
		background: #DEF;
		margin: 1.2em 0;
		border-left: 0.5em solid #8CCBF2;
	}

/******************************************************************************/
/*                                    Tables                                  */
/******************************************************************************/

	th, td {
		text-align: left;
		text-align: start;
	}

/** Property/Descriptor Definition Tables *************************************/

	table.def {
		/* inherits .def box styling, see above */
		width: 100%;
		border-spacing: 0;
	}

	table.def td,
	table.def th {
		padding: 0.5em;
		vertical-align: baseline;
		border-bottom: 1px solid #bbd7e9;
	}

	table.def > tbody > tr:last-child th,
	table.def > tbody > tr:last-child td {
		border-bottom: 0;
	}

	table.def th {
		font-style: italic;
		font-weight: normal;
		padding-left: 1em;
		width: 3em;
	}

	/* For when values are extra-complex and need formatting for readability */
	table td.pre {
		white-space: pre-wrap;
	}

	/* A footnote at the bottom of a def table */
	table.def           td.footnote {
		padding-top: 0.6em;
	}
	table.def           td.footnote::before {
		content: " ";
		display: block;
		height: 0.6em;
		width: 4em;
		border-top: thin solid;
	}

/** Data tables (and properly marked-up index tables) *************************/
	/*
		 <table class="data"> highlights structural relationships in a table
		 when correct markup is used (e.g. thead/tbody, th vs. td, scope attribute)

		 Use class="complex data" for particularly complicated tables --
		 (This will draw more lines: busier, but clearer.)

		 Use class="long" on table cells with paragraph-like contents
		 (This will adjust text alignment accordingly.)
		 Alternately use class="longlastcol" on tables, to have the last column assume "long".
	*/

	table {
		word-wrap: normal;
		overflow-wrap: normal;
		hyphens: manual;
	}

	table.data,
	table.index {
		margin: 1em auto;
		border-collapse: collapse;
		border: hidden;
		width: 100%;
	}
	table.data caption,
	table.index caption {
		max-width: 50em;
		margin: 0 auto 1em;
	}

	table.data td,  table.data th,
	table.index td, table.index th {
		padding: 0.5em 1em;
		border-width: 1px;
		border-color: silver;
		border-top-style: solid;
	}

	table.data thead td:empty {
		padding: 0;
		border: 0;
	}

	table.data  thead,
	table.index thead,
	table.data  tbody,
	table.index tbody {
		border-bottom: 2px solid;
	}

	table.data colgroup,
	table.index colgroup {
		border-left: 2px solid;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		border-right: 2px solid;
		border-top: 1px solid silver;
		padding-right: 1em;
	}

	table.data th[colspan],
	table.data td[colspan] {
		text-align: center;
	}

	table.complex.data th,
	table.complex.data td {
		border: 1px solid silver;
		text-align: center;
	}

	table.data.longlastcol td:last-child,
	table.data td.long {
	 vertical-align: baseline;
	 text-align: left;
	}

	table.data img {
		vertical-align: middle;
	}


/*
Alternate table alignment rules

	table.data,
	table.index {
		text-align: center;
	}

	table.data  thead th[scope="row"],
	table.index thead th[scope="row"] {
		text-align: right;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		text-align: right;
	}

Possible extra rowspan handling

	table.data  tbody th[rowspan]:not([rowspan='1']),
	table.index tbody th[rowspan]:not([rowspan='1']),
	table.data  tbody td[rowspan]:not([rowspan='1']),
	table.index tbody td[rowspan]:not([rowspan='1']) {
		border-left: 1px solid silver;
	}

	table.data  tbody th[rowspan]:first-child,
	table.index tbody th[rowspan]:first-child,
	table.data  tbody td[rowspan]:first-child,
	table.index tbody td[rowspan]:first-child{
		border-left: 0;
		border-right: 1px solid silver;
	}
*/

/******************************************************************************/
/*                                  Indices                                   */
/******************************************************************************/


/** Table of Contents *********************************************************/

	.toc a {
		/* More spacing; use padding to make it part of the click target. */
		padding-top: 0.1rem;
		/* Larger, more consistently-sized click target */
		display: block;
		/* Reverse color scheme */
		color: black;
		border-color: #3980B5;
		border-bottom-width: 3px !important;
		margin-bottom: 0px !important;
	}
	.toc a:visited {
		border-color: #054572;
	}
	.toc a:not(:focus):not(:hover) {
		/* Allow colors to cascade through from link styling */
		border-bottom-color: transparent;
	}

	.toc, .toc ol, .toc ul, .toc li {
		list-style: none; /* Numbers must be inlined into source */
		/* because generated content isn't search/selectable and markers can't do multilevel yet */
		margin:  0;
		padding: 0;
		line-height: 1.1rem; /* consistent spacing */
	}

	/* ToC not indented until third level, but font style & margins show hierarchy */
	.toc > li             { font-weight: bold;   }
	.toc > li li          { font-weight: normal; }
	.toc > li li li       { font-size:   95%;    }
	.toc > li li li li    { font-size:   90%;    }
	.toc > li li li li li { font-size:   85%;    }

	.toc > li             { margin: 1.5rem 0;    }
	.toc > li li          { margin: 0.3rem 0;    }
	.toc > li li li       { margin-left: 2rem;   }

	/* Section numbers in a column of their own */
	.toc .secno {
		float: left;
		width: 4rem;
		white-space: nowrap;
	}
	.toc > li li li li .secno {
		font-size: 85%;
	}
	.toc > li li li li li .secno {
		font-size: 100%;
	}

	:not(li) > .toc              { margin-left:  5rem; }
	.toc .secno                  { margin-left: -5rem; }
	.toc > li li li .secno       { margin-left: -7rem; }
	.toc > li li li li .secno    { margin-left: -9rem; }
	.toc > li li li li li .secno { margin-left: -11rem; }

	/* Tighten up indentation in narrow ToCs */
	@media (max-width: 30em) {
		:not(li) > .toc              { margin-left:  4rem; }
		.toc .secno                  { margin-left: -4rem; }
		.toc > li li li              { margin-left:  1rem; }
		.toc > li li li .secno       { margin-left: -5rem; }
		.toc > li li li li .secno    { margin-left: -6rem; }
		.toc > li li li li li .secno { margin-left: -7rem; }
	}
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) :not(li) > .toc              { margin-left:  4rem; }
		body:not(.toc-inline) .toc .secno                  { margin-left: -4rem; }
		body:not(.toc-inline) .toc > li li li              { margin-left:  1rem; }
		body:not(.toc-inline) .toc > li li li .secno       { margin-left: -5rem; }
		body:not(.toc-inline) .toc > li li li li .secno    { margin-left: -6rem; }
		body:not(.toc-inline) .toc > li li li li li .secno { margin-left: -7rem; }
	}
	body.toc-sidebar #toc :not(li) > .toc              { margin-left:  4rem; }
	body.toc-sidebar #toc .toc .secno                  { margin-left: -4rem; }
	body.toc-sidebar #toc .toc > li li li              { margin-left:  1rem; }
	body.toc-sidebar #toc .toc > li li li .secno       { margin-left: -5rem; }
	body.toc-sidebar #toc .toc > li li li li .secno    { margin-left: -6rem; }
	body.toc-sidebar #toc .toc > li li li li li .secno { margin-left: -7rem; }

	.toc li {
		clear: both;
	}


/** Index *********************************************************************/

	/* Index Lists: Layout */
	ul.index       { margin-left: 0; columns: 15em; text-indent: 1em hanging; }
	ul.index li    { margin-left: 0; list-style: none; break-inside: avoid; }
	ul.index li li { margin-left: 1em }
	ul.index dl    { margin-top: 0; }
	ul.index dt    { margin: .2em 0 .2em 20px;}
	ul.index dd    { margin: .2em 0 .2em 40px;}
	/* Index Lists: Typography */
	ul.index ul,
	ul.index dl { font-size: smaller; }
	@media not print {
		ul.index li span {
			white-space: nowrap;
			color: transparent; }
		ul.index li a:hover + span,
		ul.index li a:focus + span {
			color: #707070;
		}
	}

/** Index Tables *****************************************************/
	/* See also the data table styling section, which this effectively subclasses */

	table.index {
		font-size: small;
		border-collapse: collapse;
		border-spacing: 0;
		text-align: left;
		margin: 1em 0;
	}

	table.index td,
	table.index th {
		padding: 0.4em;
	}

	table.index tr:hover td:not([rowspan]),
	table.index tr:hover th:not([rowspan]) {
		background: #f7f8f9;
	}

	/* The link in the first column in the property table (formerly a TD) */
	table.index th:first-child a {
		font-weight: bold;
	}

/******************************************************************************/
/*                                    Print                                   */
/******************************************************************************/

	@media print {
		/* Pages have their own margins. */
		html {
			margin: 0;
		}
		/* Serif for print. */
		body {
			font-family: serif;
		}
	}
	@page {
		margin: 1.5cm 1.1cm;
	}

/******************************************************************************/
/*                                    Legacy                                  */
/******************************************************************************/

	/* This rule is inherited from past style sheets. No idea what it's for. */
	.hide { display: none }



/******************************************************************************/
/*                             Overflow Control                               */
/******************************************************************************/

	.figure .caption, .sidefigure .caption, figcaption {
		/* in case figure is overlarge, limit caption to 50em */
		max-width: 50rem;
		margin-left: auto;
		margin-right: auto;
	}
	.overlarge > table {
		/* limit preferred width of table */
		max-width: 50em;
		margin-left: auto;
		margin-right: auto;
	}

	@media (min-width: 55em) {
		.overlarge {
			margin-left: calc(13px + 26.5rem - 50vw);
			margin-right: calc(13px + 26.5rem - 50vw);
			max-width: none;
		}
	}
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) .overlarge {
			/* 30.5em body padding 50em content area */
			margin-left: calc(40em - 50vw) !important;
			margin-right: calc(40em - 50vw) !important;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) .overlarge {
			/* 4em html margin 30.5em body padding 50em content area */
			margin-left: 0 !important;
			margin-right: calc(84.5em - 100vw) !important;
		}
	}

	@media not print {
		.overlarge {
			overflow-x: auto;
			/* See Lea Verou's explanation background-attachment:
			 * http://lea.verou.me/2012/04/background-attachment-local/
			 *
			background: top left  / 4em 100% linear-gradient(to right,  #ffffff, rgba(255, 255, 255, 0)) local,
			            top right / 4em 100% linear-gradient(to left, #ffffff, rgba(255, 255, 255, 0)) local,
			            top left  / 1em 100% linear-gradient(to right,  #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            top right / 1em 100% linear-gradient(to left, #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            white;
			background-repeat: no-repeat;
			*/
		}
	}
</style>
  <meta content="Bikeshed version ba473502a120361710488ab9b7f538b47858631e" name="generator">
  <link href="http://wg21.link/P0834R0" rel="canonical">
  <meta content="b4c5aae616a6942afee237b0c430bd6992585317" name="document-revision">
<style>/* style-md-lists */

/* This is a weird hack for me not yet following the commonmark spec
   regarding paragraph and lists. */
[data-md] > :first-child {
    margin-top: 0;
}
[data-md] > :last-child {
    margin-bottom: 0;
}</style>
<style>/* style-hidedel */

            #hidedel:checked ~ del, #hidedel:checked ~ * del { display:none; }
            #hidedel ~ #hidedel-label::before, #hidedel ~ * #hidedel-label::before { content: "☐ "; }
            #hidedel:checked ~ #hidedel-label::before, #hidedel:checked ~ * #hidedel-label::before { content: "☑ "; }
        </style>
<style>/* style-selflinks */

.heading, .issue, .note, .example, li, dt {
    position: relative;
}
a.self-link {
    position: absolute;
    top: 0;
    left: calc(-1 * (3.5rem - 26px));
    width: calc(3.5rem - 26px);
    height: 2em;
    text-align: center;
    border: none;
    transition: opacity .2s;
    opacity: .5;
}
a.self-link:hover {
    opacity: 1;
}
.heading > a.self-link {
    font-size: 83%;
}
li > a.self-link {
    left: calc(-1 * (3.5rem - 26px) - 2em);
}
dfn > a.self-link {
    top: auto;
    left: auto;
    opacity: 0;
    width: 1.5em;
    height: 1.5em;
    background: gray;
    color: white;
    font-style: normal;
    transition: opacity .2s, background-color .2s, color .2s;
}
dfn:hover > a.self-link {
    opacity: 1;
}
dfn > a.self-link:hover {
    color: black;
}

a.self-link::before            { content: "¶"; }
.heading > a.self-link::before { content: "§"; }
dfn > a.self-link::before      { content: "#"; }</style>
<style>/* style-counters */

body {
    counter-reset: example figure issue;
}
.issue {
    counter-increment: issue;
}
.issue:not(.no-marker)::before {
    content: "Issue " counter(issue);
}

.example {
    counter-increment: example;
}
.example:not(.no-marker)::before {
    content: "Example " counter(example);
}
.invalid.example:not(.no-marker)::before,
.illegal.example:not(.no-marker)::before {
    content: "Invalid Example" counter(example);
}

figcaption {
    counter-increment: figure;
}
figcaption:not(.no-marker)::before {
    content: "Figure " counter(figure) " ";
}</style>
<style>/* style-autolinks */

.css.css, .property.property, .descriptor.descriptor {
    color: #005a9c;
    font-size: inherit;
    font-family: inherit;
}
.css::before, .property::before, .descriptor::before {
    content: "‘";
}
.css::after, .property::after, .descriptor::after {
    content: "’";
}
.property, .descriptor {
    /* Don't wrap property and descriptor names */
    white-space: nowrap;
}
.type { /* CSS value <type> */
    font-style: italic;
}
pre .property::before, pre .property::after {
    content: "";
}
[data-link-type="property"]::before,
[data-link-type="propdesc"]::before,
[data-link-type="descriptor"]::before,
[data-link-type="value"]::before,
[data-link-type="function"]::before,
[data-link-type="at-rule"]::before,
[data-link-type="selector"]::before,
[data-link-type="maybe"]::before {
    content: "‘";
}
[data-link-type="property"]::after,
[data-link-type="propdesc"]::after,
[data-link-type="descriptor"]::after,
[data-link-type="value"]::after,
[data-link-type="function"]::after,
[data-link-type="at-rule"]::after,
[data-link-type="selector"]::after,
[data-link-type="maybe"]::after {
    content: "’";
}

[data-link-type].production::before,
[data-link-type].production::after,
.prod [data-link-type]::before,
.prod [data-link-type]::after {
    content: "";
}

[data-link-type=element],
[data-link-type=element-attr] {
    font-family: Menlo, Consolas, "DejaVu Sans Mono", monospace;
    font-size: .9em;
}
[data-link-type=element]::before { content: "<" }
[data-link-type=element]::after  { content: ">" }

[data-link-type=biblio] {
    white-space: pre;
}</style>
<style>/* style-syntax-highlighting */

.highlight:not(.idl) { background: hsl(24, 20%, 95%); }
code.highlight { padding: .1em; border-radius: .3em; }
pre.highlight, pre > code.highlight { display: block; padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0; }
.highlight .c { color: #708090 } /* Comment */
.highlight .k { color: #990055 } /* Keyword */
.highlight .l { color: #000000 } /* Literal */
.highlight .n { color: #0077aa } /* Name */
.highlight .o { color: #999999 } /* Operator */
.highlight .p { color: #999999 } /* Punctuation */
.highlight .cm { color: #708090 } /* Comment.Multiline */
.highlight .cp { color: #708090 } /* Comment.Preproc */
.highlight .c1 { color: #708090 } /* Comment.Single */
.highlight .cs { color: #708090 } /* Comment.Special */
.highlight .kc { color: #990055 } /* Keyword.Constant */
.highlight .kd { color: #990055 } /* Keyword.Declaration */
.highlight .kn { color: #990055 } /* Keyword.Namespace */
.highlight .kp { color: #990055 } /* Keyword.Pseudo */
.highlight .kr { color: #990055 } /* Keyword.Reserved */
.highlight .kt { color: #990055 } /* Keyword.Type */
.highlight .ld { color: #000000 } /* Literal.Date */
.highlight .m { color: #000000 } /* Literal.Number */
.highlight .s { color: #a67f59 } /* Literal.String */
.highlight .na { color: #0077aa } /* Name.Attribute */
.highlight .nc { color: #0077aa } /* Name.Class */
.highlight .no { color: #0077aa } /* Name.Constant */
.highlight .nd { color: #0077aa } /* Name.Decorator */
.highlight .ni { color: #0077aa } /* Name.Entity */
.highlight .ne { color: #0077aa } /* Name.Exception */
.highlight .nf { color: #0077aa } /* Name.Function */
.highlight .nl { color: #0077aa } /* Name.Label */
.highlight .nn { color: #0077aa } /* Name.Namespace */
.highlight .py { color: #0077aa } /* Name.Property */
.highlight .nt { color: #669900 } /* Name.Tag */
.highlight .nv { color: #222222 } /* Name.Variable */
.highlight .ow { color: #999999 } /* Operator.Word */
.highlight .mb { color: #000000 } /* Literal.Number.Bin */
.highlight .mf { color: #000000 } /* Literal.Number.Float */
.highlight .mh { color: #000000 } /* Literal.Number.Hex */
.highlight .mi { color: #000000 } /* Literal.Number.Integer */
.highlight .mo { color: #000000 } /* Literal.Number.Oct */
.highlight .sb { color: #a67f59 } /* Literal.String.Backtick */
.highlight .sc { color: #a67f59 } /* Literal.String.Char */
.highlight .sd { color: #a67f59 } /* Literal.String.Doc */
.highlight .s2 { color: #a67f59 } /* Literal.String.Double */
.highlight .se { color: #a67f59 } /* Literal.String.Escape */
.highlight .sh { color: #a67f59 } /* Literal.String.Heredoc */
.highlight .si { color: #a67f59 } /* Literal.String.Interpol */
.highlight .sx { color: #a67f59 } /* Literal.String.Other */
.highlight .sr { color: #a67f59 } /* Literal.String.Regex */
.highlight .s1 { color: #a67f59 } /* Literal.String.Single */
.highlight .ss { color: #a67f59 } /* Literal.String.Symbol */
.highlight .vc { color: #0077aa } /* Name.Variable.Class */
.highlight .vg { color: #0077aa } /* Name.Variable.Global */
.highlight .vi { color: #0077aa } /* Name.Variable.Instance */
.highlight .il { color: #000000 } /* Literal.Number.Integer.Long */
</style>
 <body class="h-entry">
  <input id="hidedel" style="display:none" type="checkbox">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">p0834r0<br>Lifting overload sets into objects</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Published Proposal, <time class="dt-updated" datetime="2017-10-16">16 October 2017</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="http://wg21.link/P0834R0">http://wg21.link/P0834R0</a>
     <dt>Author:
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:griwes@griwes.info">Michał Dominiak</a> (<span class="p-org org">Nokia Networks</span>)
     <dt>Audience:
     <dd>EWG
     <dt>Toggle Diffs:
     <dd>
      <label for="hidedel" id="hidedel-label">Hide deleted text</label>
     <dt>Project:
     <dd>ISO JTC1/SC22/WG21: Programming Language C++
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <div class="p-summary" data-fill-with="abstract">
   <h2 class="no-num no-toc no-ref heading settled" id="abstract"><span class="content">Abstract</span></h2>
   <p>Passing overload sets around made easy</p>
  </div>
  <nav data-fill-with="table-of-contents" id="toc">
   <h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2>
   <ol class="toc" role="directory">
    <li>
     <a href="#intro"><span class="secno">1</span> <span class="content">Introduction</span></a>
     <ol class="toc">
      <li><a href="#motivation"><span class="secno">1.1</span> <span class="content">Motivation</span></a>
      <li><a href="#previous-standardization-attempts"><span class="secno">1.2</span> <span class="content">Previous standardization attempts</span></a>
      <li><a href="#conventions"><span class="secno">1.3</span> <span class="content">Conventions</span></a>
     </ol>
    <li>
     <a href="#core"><span class="secno">2</span> <span class="content">Core proposal</span></a>
     <ol class="toc">
      <li><a href="#passing-overloaded-functions"><span class="secno">2.1</span> <span class="content">Passing overloaded functions</span></a>
      <li><a href="#passing-operators"><span class="secno">2.2</span> <span class="content">Passing operators</span></a>
      <li><a href="#member-access"><span class="secno">2.3</span> <span class="content">Member access</span></a>
      <li><a href="#members-vs-member-functions"><span class="secno">2.4</span> <span class="content">Members vs member functions</span></a>
      <li><a href="#impact-on-the-standard"><span class="secno">2.5</span> <span class="content">Impact on the standard</span></a>
     </ol>
    <li>
     <a href="#considerations"><span class="secno">3</span> <span class="content">Things to consider</span></a>
     <ol class="toc">
      <li><a href="#forced-materialization"><span class="secno">3.1</span> <span class="content">Forced materialization</span></a>
      <li><a href="#further-generalization-of-the-feature"><span class="secno">3.2</span> <span class="content">Further generalization of the feature</span></a>
     </ol>
    <li><a href="#ack"><span class="secno">4</span> <span class="content">Acknowledgements</span></a>
   </ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="intro"><span class="secno">1. </span><span class="content">Introduction</span><a class="self-link" href="#intro"></a></h2>
   <h3 class="heading settled" data-level="1.1" id="motivation"><span class="secno">1.1. </span><span class="content">Motivation</span><a class="self-link" href="#motivation"></a></h3>
   <p>Passing functions around in C++ is a common occurence, however it’s an extremely difficult thing to do when you want to
pass an entire overload set into another function. In some cases, you can simply pass a function pointer - but that can’t
be relied upon for, for example, standard functions, as standard functions have no guaranteed signatures.</p>
   <p>One way that somewhat captures the intent of "call a function called <code class="highlight"><span class="n">foo</span></code>" is:</p>
<pre class="language-cpp highlight"><span class="k">auto</span> <span class="n">overload_set</span> <span class="o">=</span> <span class="p">[](</span><span class="k">auto</span> <span class="o">&amp;&amp;</span><span class="p">...</span> <span class="n">args</span><span class="p">)</span>
    <span class="o">-></span> <span class="k">decltype</span><span class="p">(</span><span class="n">foo</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="k">decltype</span><span class="p">(</span><span class="n">args</span><span class="p">)</span><span class="o">></span><span class="p">(</span><span class="n">args</span><span class="p">)...))</span>
<span class="p">{</span>
    <span class="k">return</span> <span class="n">foo</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="k">decltype</span><span class="p">(</span><span class="n">args</span><span class="p">)</span><span class="o">></span><span class="p">(</span><span class="n">args</span><span class="p">)...);</span>
<span class="p">};</span>
</pre>
   <p>This can be simplified with a macro, but I believe that a dedicated language feature that can handle more cases than just
named functions is a good idea; other things that the proposed syntax can be extended to is operators or member access.</p>
   <p>A more concrete motivating example has been given in P0119:</p>
<pre class="language-cpp highlight"><span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
<span class="n">T</span> <span class="n">twice</span><span class="p">(</span><span class="n">T</span> <span class="n">x</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">x</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">It</span><span class="o">></span>
<span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="n">It</span> <span class="n">first</span><span class="p">,</span> <span class="n">It</span> <span class="n">second</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">transform</span><span class="p">(</span><span class="n">first</span><span class="p">,</span> <span class="n">second</span><span class="p">,</span> <span class="n">first</span><span class="p">,</span> <span class="n">twice</span><span class="p">);</span>
<span class="p">}</span>
</pre>
   <p>This currently doesn’t work; and this paper doesn’t propose to make it work. Instead, it proposes we introduce the
following syntax:</p>
<pre class="language-cpp highlight"><span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">It</span><span class="o">></span>
<span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="n">It</span> <span class="n">first</span><span class="p">,</span> <span class="n">It</span> <span class="n">second</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">transform</span><span class="p">(</span><span class="n">first</span><span class="p">,</span> <span class="n">second</span><span class="p">,</span> <span class="n">first</span><span class="p">,</span> <span class="p">[]</span><span class="n">twice</span><span class="p">);</span>
<span class="p">}</span>
</pre>
   <h3 class="heading settled" data-level="1.2" id="previous-standardization-attempts"><span class="secno">1.2. </span><span class="content">Previous standardization attempts</span><a class="self-link" href="#previous-standardization-attempts"></a></h3>
   <p>The original proposal is <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3617.htm">N3617</a>. Later, this functionality
has been proposed in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0119r2.pdf">P0119</a>, which attempted
to remove the syntax requirement for the lambda introducers; this caused problems that were discovered during the
discussion in Oulu. The problems included, but were not limited to, ODR issues; more information can be found in the
discussion notes.</p>
   <p>This proposal goes back to the syntax using lambda introducers, but with a different take on member accessors.</p>
   <p>The original paper also introduced a notion of <code class="highlight"><span class="n">LIFTED_INVOKE</span></code>, which this paper doesn’t attempt to do. I intend to
go with this paper, as a design paper, through EWG, and then come back again to apply any comments and actually
provide wording. If the recommendation is to invent something similar to <code class="highlight"><span class="n">INVOKE</span></code>, I will do that.</p>
   <h3 class="heading settled" data-level="1.3" id="conventions"><span class="secno">1.3. </span><span class="content">Conventions</span><a class="self-link" href="#conventions"></a></h3>
   <p>To make the code snippets more readable, this paper assumes the following macro:</p>
<pre class="language-cpp highlight"><span class="cp">#define FWD(...) std::forward&lt;decltype(__VA_ARGS__)>(__VA_ARGS__)</span>
</pre>
   <h2 class="heading settled" data-level="2" id="core"><span class="secno">2. </span><span class="content">Core proposal</span><a class="self-link" href="#core"></a></h2>
   <h3 class="heading settled" data-level="2.1" id="passing-overloaded-functions"><span class="secno">2.1. </span><span class="content">Passing overloaded functions</span><a class="self-link" href="#passing-overloaded-functions"></a></h3>
   <p>The core of the proposal is the ability to pass functions "by name", that is - to pass an object representing
an entire overload set around. The basic transformation would be from</p>
<pre class="highlight"><span class="p">[]</span><span class="o">&lt;</span><span class="n">id</span><span class="o">-</span><span class="n">expression</span><span class="o">></span>
</pre>
   <p>into</p>
<pre class="highlight"><span class="p">[](</span><span class="k">auto</span> <span class="o">&amp;&amp;</span><span class="p">...</span> <span class="n">args</span><span class="p">)</span>
    <span class="k">noexcept</span><span class="p">(</span><span class="k">noexcept</span><span class="p">(</span><span class="o">&lt;</span><span class="n">id</span><span class="o">-</span><span class="n">expression</span><span class="o">></span><span class="p">(</span><span class="n">FWD</span><span class="p">(</span><span class="n">args</span><span class="p">)...)))</span>
    <span class="o">-></span> <span class="k">decltype</span><span class="p">(</span><span class="o">&lt;</span><span class="n">id</span><span class="o">-</span><span class="n">expression</span><span class="o">></span><span class="p">(</span><span class="n">FWD</span><span class="p">(</span><span class="n">args</span><span class="p">)...))</span>
<span class="p">{</span>
    <span class="k">return</span> <span class="o">&lt;</span><span class="n">id</span><span class="o">-</span><span class="n">expression</span><span class="o">></span><span class="p">(</span><span class="n">FWD</span><span class="p">(</span><span class="n">args</span><span class="p">)...);</span>
<span class="p">}</span>
</pre>
   <p>Notice that this proposes the syntax to allow <code class="highlight"><span class="n">id</span><span class="o">-</span><span class="n">expressions</span></code>; this means that expressions like <code class="highlight"><span class="p">[]</span><span class="n">std</span><span class="o">::</span><span class="n">addressof</span></code> would be valid, which solves the problem of "can’t rely on specific signatures in <code class="highlight"><span class="n">std</span><span class="o">::</span></code>").</p>
   <h3 class="heading settled" data-level="2.2" id="passing-operators"><span class="secno">2.2. </span><span class="content">Passing operators</span><a class="self-link" href="#passing-operators"></a></h3>
   <p>The second proposed form is</p>
<pre class="highlight"><span class="p">[]</span>@
</pre>
   <p>where <code class="highlight">@</code> is an operator. This would be transformed into (assuming <code class="highlight">@</code> is binary)</p>
<pre class="highlight"><span class="p">[](</span><span class="k">auto</span> <span class="o">&amp;&amp;</span> <span class="n">arg1</span><span class="p">,</span> <span class="k">auto</span> <span class="o">&amp;&amp;</span> <span class="n">arg2</span><span class="p">)</span>
    <span class="k">noexcept</span><span class="p">(</span><span class="k">noexcept</span><span class="p">(</span><span class="n">FWD</span><span class="p">(</span><span class="n">arg1</span><span class="p">)</span> @ <span class="n">FWD</span><span class="p">(</span><span class="n">arg2</span><span class="p">)))</span>
    <span class="o">-></span> <span class="k">decltype</span><span class="p">(</span><span class="n">FWD</span><span class="p">(</span><span class="n">arg1</span><span class="p">)</span> @ <span class="n">FWD</span><span class="p">(</span><span class="n">arg2</span><span class="p">))</span>
<span class="p">{</span>
    <span class="k">return</span> <span class="n">FWD</span><span class="p">(</span><span class="n">arg1</span><span class="p">)</span> @ <span class="n">FWD</span><span class="p">(</span><span class="n">arg2</span><span class="p">);</span>
<span class="p">}</span>
</pre>
   <p>This is arguably already provided by the family of <code class="highlight"><span class="n">std</span><span class="o">::</span><span class="n">less</span><span class="o">&lt;></span></code>, but <code class="highlight"><span class="p">[]</span><span class="o">&lt;</span></code> is much shorter than <code class="highlight"><span class="n">std</span><span class="o">::</span><span class="n">less</span><span class="o">&lt;></span><span class="p">()</span></code>.</p>
   <p>For unary operators:</p>
<pre class="highlight"><span class="p">[](</span><span class="k">auto</span> <span class="o">&amp;&amp;</span> <span class="n">arg</span><span class="p">)</span>
    <span class="k">noexcept</span><span class="p">(</span>@ <span class="n">FWD</span><span class="p">(</span><span class="n">arg</span><span class="p">)))</span>
    <span class="o">-></span> <span class="k">decltype</span><span class="p">(</span>@ <span class="n">FWD</span><span class="p">(</span><span class="n">arg</span><span class="p">))</span>
<span class="p">{</span>
    <span class="k">return</span> @ <span class="n">FWD</span><span class="p">(</span><span class="n">arg</span><span class="p">);</span>
<span class="p">}</span>
</pre>
   <p>For operators that can be both unary and binary, like <code class="highlight"><span class="o">+</span></code>, <code class="highlight"><span class="p">[]</span>@</code> would create a function object that can be called
in both ways.</p>
   <p>There’s four operators that are somewhat problematic here, as they don’t follow the general pattern.</p>
   <ol>
    <li data-md="">
     <p>The call operator object <code class="highlight"><span class="p">[]()</span></code> - I do not know whether this can be made unambiquous enough, but even if it can -
I’m not sure if we want to introduce a potential source of confusion (against <code class="highlight"><span class="p">[](){}</span></code>).</p>
    <li data-md="">
     <p>The indexing operator object <code class="highlight"><span class="p">[][]</span></code> - this looks funny, but should be workable, and the semantics are pretty obvious.</p>
    <li data-md="">
     <p>The <code class="highlight"><span class="p">[]</span><span class="o">++</span></code> and <code class="highlight"><span class="p">[]</span><span class="o">--</span></code> operators. P0119 proposes that they should always only mean pre-increment and pre-decrement,
and I agree with that judgement, but I wouldn’t be too irritated if we just ignored them and decided to not support
the silliness.</p>
   </ol>
   <p>One solution for (1) and (2) would be to require the syntax to be <code class="highlight"><span class="p">[]</span><span class="k">operator</span><span class="p">()</span></code> or <code class="highlight"><span class="p">[]</span><span class="k">operator</span><span class="p">[]</span></code>, but that is quite
verbose. An argument can be made for allowing this more verbose form for all operators, that is to make <code class="highlight"><span class="p">[]</span>@</code> equivalent
to <code class="highlight"><span class="p">[]</span><span class="k">operator</span>@</code> in all cases where it is allowed.</p>
   <h3 class="heading settled" data-level="2.3" id="member-access"><span class="secno">2.3. </span><span class="content">Member access</span><a class="self-link" href="#member-access"></a></h3>
   <p>The final form proposed is related to accessing members of structures and classes. Currently the only way to pass
a <em>thing</em> naming a specific member is to pass a member function pointer or a member pointer around. Those are unwieldy,
and are not generic, that is point to a specific member of a specific class, generally by an offset or something similar.
But more frequently what we need is a tool to actually allow us to <em>name</em> a member, and have that named member reference
be generic, i.e. usable with different types.</p>
   <p>The proposed syntax differs from the original paper, and uses a disambiguator to clearly state whether a lifted object is
meant to be a free function or a member; that is:</p>
<pre class="highlight"><span class="p">[].</span><span class="o">&lt;</span><span class="n">identifier</span><span class="o">></span>
</pre>
   <p>would be transformed into</p>
<pre class="highlight"><span class="p">[](</span><span class="k">auto</span> <span class="o">&amp;&amp;</span> <span class="n">object</span><span class="p">)</span> <span class="k">noexcept</span>
    <span class="o">-></span> <span class="k">decltype</span><span class="p">((</span><span class="n">FWD</span><span class="p">(</span><span class="n">object</span><span class="p">).</span><span class="o">&lt;</span><span class="n">identifier</span><span class="o">></span><span class="p">))</span> <span class="c1">// intentional double parentheses</span>
<span class="c1"></span><span class="p">{</span>
    <span class="k">return</span> <span class="n">FWD</span><span class="p">(</span><span class="n">object</span><span class="p">).</span><span class="o">&lt;</span><span class="n">identifier</span><span class="o">></span><span class="p">;</span>
<span class="p">}</span>
</pre>
   <p>This would again allow us to make this example from the original paper (only slightly modified) compile:</p>
<pre class="language-cpp highlight"><span class="k">struct</span> <span class="n">user</span><span class="p">{</span>
    <span class="kt">int</span> <span class="n">id</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name</span><span class="p">;</span>
<span class="p">};</span>

<span class="kt">void</span> <span class="nf">f</span><span class="p">()</span>
    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">user</span><span class="o">></span> <span class="n">users</span><span class="p">{</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="s">"Bjarne"</span><span class="p">},</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="s">"Herb"</span><span class="p">},</span> <span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="s">"Scott"</span><span class="p">},</span> <span class="p">{</span><span class="mi">0</span><span class="p">,</span> <span class="s">"Stephan"</span><span class="p">},</span> <span class="p">{</span><span class="mi">2</span><span class="p">,</span> <span class="s">"Andrei"</span><span class="p">}</span> <span class="p">};</span>
    <span class="c1">// ordered_by implementation left as an exercise to the reader</span>
<span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">sort</span><span class="p">(</span><span class="n">users</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">users</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="n">ordered_by</span><span class="p">([].</span><span class="n">id</span><span class="p">));</span>
    <span class="c1">// [(0, "STL"), (1, "Herb"), (2, "Andrei"), (3, "Scott"), (4, "Bjarne")]</span>
<span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">sort</span><span class="p">(</span><span class="n">users</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">users</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="n">ordered_by</span><span class="p">([].</span><span class="n">name</span><span class="p">));</span>
    <span class="c1">// [(2, "Andrei"), (4, "Bjarne"), (1, "Herb"), (3, "Scott"), (0, "Stephan")]</span>
<span class="c1"></span><span class="p">}</span>
</pre>
   <h3 class="heading settled" data-level="2.4" id="members-vs-member-functions"><span class="secno">2.4. </span><span class="content">Members vs member functions</span><a class="self-link" href="#members-vs-member-functions"></a></h3>
   <p>When <code class="highlight"><span class="p">[].</span><span class="o">&lt;</span><span class="n">identifier</span><span class="o">></span></code> refers to a data member, there’s no easy way to actually specify "I want to name a member
function and invoke it", instead of "I want to name a data member". We could invent a weird and outlandish syntax
like <code class="highlight"><span class="p">[].()</span><span class="o">&lt;</span><span class="n">identifier</span><span class="o">></span></code>, but despite that being quite short, it doesn’t look very good, and the gut feeling is that
it’s too close to Haskell’s variety of operators for the sanity of C++ programmers.</p>
   <p>One way to approach this, proposed in a discussion by Tomasz Kamiński, is to always invoke when possible, and return
a value if not. We could also return when not a function and call otherwise. Personally I consider this troublesome;
the meaning of code can silently change without detecting something that should be an error, when the lifted accessor
does too much magic. Consider</p>
<pre class="language-cpp highlight"><span class="k">struct</span> <span class="n">foo</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">a</span><span class="p">;</span>
<span class="p">};</span>
</pre>
   <p>If we call <code class="highlight"><span class="p">[].</span><span class="n">a</span></code> with an instance of <code class="highlight"><span class="n">foo</span></code>, we will be given a reference to the member. However, if someone changes
the definition to the following:</p>
<pre class="language-cpp highlight"><span class="k">struct</span> <span class="n">foo</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">a</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="p">};</span>
</pre>
   <p>then <code class="highlight"><span class="p">[].</span><span class="n">a</span></code> will continue to work on instances of <code class="highlight"><span class="n">foo</span></code>, even though the meaning changed. However, all other places
that just access <code class="highlight"><span class="n">foo</span><span class="o">::</span><span class="n">a</span></code> directly, not via a lifting expression, will stop compiling. On the flip side, if we have
the second definition, and someone changes it to</p>
<pre class="language-cpp highlight"><span class="k">struct</span> <span class="n">foo</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">function</span><span class="o">&lt;</span><span class="kt">int</span> <span class="p">()</span><span class="o">></span> <span class="n">a</span><span class="p">;</span>
<span class="p">};</span>
</pre>
   <p>then, depending on whether we chose to call if we can, or to return if we can, we will only have the ability to lift
a call to <code class="highlight"><span class="n">foo</span><span class="o">::</span><span class="n">a</span></code>, or to lift an access of <code class="highlight"><span class="n">foo</span><span class="o">::</span><span class="n">a</span></code>; we won’t have both; and despite the change being source-compatible
everywhere else, it can be an incompatible change in the presence of lifted accessors.</p>
   <p>If we decide to have a dedicated syntax for lifting member accesses, and a dedicated syntax for lifting member calls,
then both those operations are always possible to explicitly express, the meaning of code won’t silently change without
causing a compilation error, and will keep compiling through source-compatible changes.</p>
   <h3 class="heading settled" data-level="2.5" id="impact-on-the-standard"><span class="secno">2.5. </span><span class="content">Impact on the standard</span><a class="self-link" href="#impact-on-the-standard"></a></h3>
   <p>The proposed syntax is currently invalid, so there’s no impact on other parts of the standard or other features.</p>
   <p>Abbreviated lambdas may potentially have impact on this feature, if they get accepted, by simplifying the specification
of what lifted expressions are transformed into. (Unless we want to specify this differently, to avoid the forced
materialization issue mentioned below.)</p>
   <h2 class="heading settled" data-level="3" id="considerations"><span class="secno">3. </span><span class="content">Things to consider</span><a class="self-link" href="#considerations"></a></h2>
   <h3 class="heading settled" data-level="3.1" id="forced-materialization"><span class="secno">3.1. </span><span class="content">Forced materialization</span><a class="self-link" href="#forced-materialization"></a></h3>
   <p>In an email discussion, Tomasz Kamiński mentioned one problem with the naive transformations presented in this paper
as the workaround and as the equivalent of <code class="highlight"><span class="p">[]</span><span class="n">foo</span></code>: they will force a materialization of an object potentially too
early and potentially invoke an additional move constructor, when used over a function directly.</p>
   <p>To spell the issue out more directly in code: if we currently have a following function:</p>
<pre class="language-cpp highlight"><span class="kt">void</span> <span class="nf">f</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">);</span>
</pre>
   <p>The invocation in the form of <code class="highlight"><span class="n">f</span><span class="p">(</span><span class="s">"abc"</span><span class="n">s</span><span class="p">)</span></code> will directly initialize argument. However if the function is wrapped in a
"perfectly" forwarding lambda, or lift it by writing <code class="highlight"><span class="k">auto</span> <span class="n">lf</span> <span class="o">=</span> <span class="p">[]</span><span class="n">f</span><span class="p">;</span></code>, the <code class="highlight"><span class="n">lf</span><span class="p">(</span><span class="s">"abc"</span><span class="n">s</span><span class="p">)</span></code> invocation will perform an
additional move over <code class="highlight"><span class="n">f</span><span class="p">(</span><span class="s">"abc"</span><span class="n">s</span><span class="p">)</span></code>.</p>
   <p>This is a general problem with "perfect" forwarding an materialization, but we might be able to somehow solve it for
this particular case, by making the calls through <code class="highlight"><span class="p">[]</span><span class="n">f</span></code> equivalent to just calling <code class="highlight"><span class="n">f</span></code> directly.</p>
   <p>This might be one reason to reinvent <code class="highlight"><span class="n">LIFTED_INVOKE</span></code> from the original paper, but further investigation into
viability and exact semantics would be required.</p>
   <h3 class="heading settled" data-level="3.2" id="further-generalization-of-the-feature"><span class="secno">3.2. </span><span class="content">Further generalization of the feature</span><a class="self-link" href="#further-generalization-of-the-feature"></a></h3>
   <p>Barry Rezvin mentioned that this feature feels weirdly specific, and doesn’t by itself support things like adding
arguments into the call. I understand the sentiment, and perhaps there’s a way to make that work, but I’m quite
convinced that it doesn’t belong to this particular feature; it might be a pretty good extension though, if we
figure out the details.</p>
   <h2 class="heading settled" data-level="4" id="ack"><span class="secno">4. </span><span class="content">Acknowledgements</span><a class="self-link" href="#ack"></a></h2>
   <p>I’d like to thank Philipp Juschka for the original proposal, Andrew Sutton for picking it up later on, and again Andrew,
this time together with Tomasz Kamiński, for further input and comments.</p>
  </main>
<script>
(function() {
  "use strict";
  var collapseSidebarText = '<span aria-hidden="true">←</span> '
                          + '<span>Collapse Sidebar</span>';
  var expandSidebarText   = '<span aria-hidden="true">→</span> '
                          + '<span>Pop Out Sidebar</span>';
  var tocJumpText         = '<span aria-hidden="true">↑</span> '
                          + '<span>Jump to Table of Contents</span>';

  var sidebarMedia = window.matchMedia('screen and (min-width: 78em)');
  var autoToggle   = function(e){ toggleSidebar(e.matches) };
  if(sidebarMedia.addListener) {
    sidebarMedia.addListener(autoToggle);
  }

  function toggleSidebar(on) {
    if (on == undefined) {
      on = !document.body.classList.contains('toc-sidebar');
    }

    /* Don’t scroll to compensate for the ToC if we’re above it already. */
    var headY = 0;
    var head = document.querySelector('.head');
    if (head) {
      // terrible approx of "top of ToC"
      headY += head.offsetTop + head.offsetHeight;
    }
    var skipScroll = window.scrollY < headY;

    var toggle = document.getElementById('toc-toggle');
    var tocNav = document.getElementById('toc');
    if (on) {
      var tocHeight = tocNav.offsetHeight;
      document.body.classList.add('toc-sidebar');
      document.body.classList.remove('toc-inline');
      toggle.innerHTML = collapseSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, 0 - tocHeight);
      }
      tocNav.focus();
      sidebarMedia.addListener(autoToggle); // auto-collapse when out of room
    }
    else {
      document.body.classList.add('toc-inline');
      document.body.classList.remove('toc-sidebar');
      toggle.innerHTML = expandSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, tocNav.offsetHeight);
      }
      if (toggle.matches(':hover')) {
        /* Unfocus button when not using keyboard navigation,
           because I don’t know where else to send the focus. */
        toggle.blur();
      }
    }
  }

  function createSidebarToggle() {
    /* Create the sidebar toggle in JS; it shouldn’t exist when JS is off. */
    var toggle = document.createElement('a');
      /* This should probably be a button, but appearance isn’t standards-track.*/
    toggle.id = 'toc-toggle';
    toggle.class = 'toc-toggle';
    toggle.href = '#toc';
    toggle.innerHTML = collapseSidebarText;

    sidebarMedia.addListener(autoToggle);
    var toggler = function(e) {
      e.preventDefault();
      sidebarMedia.removeListener(autoToggle); // persist explicit off states
      toggleSidebar();
      return false;
    }
    toggle.addEventListener('click', toggler, false);


    /* Get <nav id=toc-nav>, or make it if we don’t have one. */
    var tocNav = document.getElementById('toc-nav');
    if (!tocNav) {
      tocNav = document.createElement('p');
      tocNav.id = 'toc-nav';
      /* Prepend for better keyboard navigation */
      document.body.insertBefore(tocNav, document.body.firstChild);
    }
    /* While we’re at it, make sure we have a Jump to Toc link. */
    var tocJump = document.getElementById('toc-jump');
    if (!tocJump) {
      tocJump = document.createElement('a');
      tocJump.id = 'toc-jump';
      tocJump.href = '#toc';
      tocJump.innerHTML = tocJumpText;
      tocNav.appendChild(tocJump);
    }

    tocNav.appendChild(toggle);
  }

  var toc = document.getElementById('toc');
  if (toc) {
    createSidebarToggle();
    toggleSidebar(sidebarMedia.matches);

    /* If the sidebar has been manually opened and is currently overlaying the text
       (window too small for the MQ to add the margin to body),
       then auto-close the sidebar once you click on something in there. */
    toc.addEventListener('click', function(e) {
      if(e.target.tagName.toLowerCase() == "a" && document.body.classList.contains('toc-sidebar') && !sidebarMedia.matches) {
        toggleSidebar(false);
      }
    }, false);
  }
  else {
    console.warn("Can’t find Table of Contents. Please use <nav id='toc'> around the ToC.");
  }

  /* Wrap tables in case they overflow */
  var tables = document.querySelectorAll(':not(.overlarge) > table.data, :not(.overlarge) > table.index');
  var numTables = tables.length;
  for (var i = 0; i < numTables; i++) {
    var table = tables[i];
    var wrapper = document.createElement('div');
    wrapper.className = 'overlarge';
    table.parentNode.insertBefore(wrapper, table);
    wrapper.appendChild(table);
  }

})();
</script>