<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Better lookups for `map` and `unordered_map`</title>
  <style>
      code{white-space: pre-wrap;}
      span.smallcaps{font-variant: small-caps;}
      span.underline{text-decoration: underline;}
      div.column{display: inline-block; vertical-align: top; width: 50%;}
      div.csl-block{margin-left: 1.5em;}
      ul.task-list{list-style: none;}
      pre > code.sourceCode { white-space: pre; position: relative; }
      pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
      pre > code.sourceCode > span:empty { height: 1.2em; }
      .sourceCode { overflow: visible; }
      code.sourceCode > span { color: inherit; text-decoration: inherit; }
      div.sourceCode { margin: 1em 0; }
      pre.sourceCode { margin: 0; }
      @media screen {
      div.sourceCode { overflow: auto; }
      }
      @media print {
      pre > code.sourceCode { white-space: pre-wrap; }
      pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
      }
      pre.numberSource code
        { counter-reset: source-line 0; }
      pre.numberSource code > span
        { position: relative; left: -4em; counter-increment: source-line; }
      pre.numberSource code > span > a:first-child::before
        { content: counter(source-line);
          position: relative; left: -1em; text-align: right; vertical-align: baseline;
          border: none; display: inline-block;
          -webkit-touch-callout: none; -webkit-user-select: none;
          -khtml-user-select: none; -moz-user-select: none;
          -ms-user-select: none; user-select: none;
          padding: 0 4px; width: 4em;
          color: #aaaaaa;
        }
      pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
      div.sourceCode
        {  background-color: #f6f8fa; }
      @media screen {
      pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
      }
      code span { } /* Normal */
      code span.al { color: #ff0000; } /* Alert */
      code span.an { } /* Annotation */
      code span.at { } /* Attribute */
      code span.bn { color: #9f6807; } /* BaseN */
      code span.bu { color: #9f6807; } /* BuiltIn */
      code span.cf { color: #00607c; } /* ControlFlow */
      code span.ch { color: #9f6807; } /* Char */
      code span.cn { } /* Constant */
      code span.co { color: #008000; font-style: italic; } /* Comment */
      code span.cv { color: #008000; font-style: italic; } /* CommentVar */
      code span.do { color: #008000; } /* Documentation */
      code span.dt { color: #00607c; } /* DataType */
      code span.dv { color: #9f6807; } /* DecVal */
      code span.er { color: #ff0000; font-weight: bold; } /* Error */
      code span.ex { } /* Extension */
      code span.fl { color: #9f6807; } /* Float */
      code span.fu { } /* Function */
      code span.im { } /* Import */
      code span.in { color: #008000; } /* Information */
      code span.kw { color: #00607c; } /* Keyword */
      code span.op { color: #af1915; } /* Operator */
      code span.ot { } /* Other */
      code span.pp { color: #6f4e37; } /* Preprocessor */
      code span.re { } /* RegionMarker */
      code span.sc { color: #9f6807; } /* SpecialChar */
      code span.ss { color: #9f6807; } /* SpecialString */
      code span.st { color: #9f6807; } /* String */
      code span.va { } /* Variable */
      code span.vs { color: #9f6807; } /* VerbatimString */
      code span.wa { color: #008000; font-weight: bold; } /* Warning */
      code.diff {color: #898887}
      code.diff span.va {color: #006e28}
      code.diff span.st {color: #bf0303}
  </style>
  <style type="text/css">
body {
margin: 5em;
font-family: serif;

hyphens: auto;
line-height: 1.35;
text-align: justify;
}
@media screen and (max-width: 30em) {
body {
margin: 1.5em;
}
}
div.wrapper {
max-width: 60em;
margin: auto;
}

ul {
list-style-type: none;
padding-left: 2.5em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
ol {
padding-left: 2.5em;
}
a {
text-decoration: none;
color: #4183C4;
}
a.hidden_link {
text-decoration: none;
color: inherit;
}
li {
margin-top: 0.6em;
margin-bottom: 0.6em;
}
h1, h2, h3, h4 {
position: relative;
line-height: 1;
}
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;
font-family: sans-serif;
font-weight: normal;
font-size: 83%;
}
a.self-link:hover { opacity: 1; }
a.self-link::before { content: "§"; }
ul > li:before {
content: "\2014";
position: absolute;
margin-left: -1.5em;
}

#TOC ul > li:before {
content: none;
}
#TOC > ul {
padding-left: 0;
}

.toc-section-number {
margin-right: 0.5em;
}
:target { background-color: #C9FBC9; }
:target .codeblock { background-color: #C9FBC9; }
:target ul { background-color: #C9FBC9; }
.abbr_ref { float: right; }
.folded_abbr_ref { float: right; }
:target .folded_abbr_ref { display: none; }
:target .unfolded_abbr_ref { float: right; display: inherit; }
.unfolded_abbr_ref { display: none; }
.secnum { display: inline-block; min-width: 35pt; }
.header-section-number { display: inline-block; min-width: 35pt; }
.annexnum { display: block; }
div.sourceLinkParent {
float: right;
}
a.sourceLink {
position: absolute;
opacity: 0;
margin-left: 10pt;
}
a.sourceLink:hover {
opacity: 1;
}
a.itemDeclLink {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
opacity: 0;
}
a.itemDeclLink:hover { opacity: 1; }
span.marginalizedparent {
position: relative;
left: -5em;
}
li span.marginalizedparent { left: -7em; }
li ul > li span.marginalizedparent { left: -9em; }
li ul > li ul > li span.marginalizedparent { left: -11em; }
li ul > li ul > li ul > li span.marginalizedparent { left: -13em; }
div.footnoteNumberParent {
position: relative;
left: -4.7em;
}
a.marginalized {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
}
a.enumerated_item_num {
position: relative;
left: -3.5em;
display: inline-block;
margin-right: -3em;
text-align: right;
width: 3em;
}
div.para { margin-bottom: 0.6em; margin-top: 0.6em; text-align: justify; }
div.section { text-align: justify; }
div.sentence { display: inline; }
span.indexparent {
display: inline;
position: relative;
float: right;
right: -1em;
}
a.index {
position: absolute;
display: none;
}
a.index:before { content: "⟵"; }

a.index:target {
display: inline;
}
.indexitems {
margin-left: 2em;
text-indent: -2em;
}
div.itemdescr {
margin-left: 3em;
}
.bnf {
font-family: serif;
margin-left: 40pt;
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.ncbnf {
font-family: serif;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
}
.ncsimplebnf {
font-family: serif;
font-style: italic;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
background: inherit; 
}
span.textnormal {
font-style: normal;
font-family: serif;
white-space: normal;
display: inline-block;
}
span.rlap {
display: inline-block;
width: 0px;
}
span.descr { font-style: normal; font-family: serif; }
span.grammarterm { font-style: italic; }
span.term { font-style: italic; }
span.terminal { font-family: monospace; font-style: normal; }
span.nonterminal { font-style: italic; }
span.tcode { font-family: monospace; font-style: normal; }
span.textbf { font-weight: bold; }
span.textsc { font-variant: small-caps; }
a.nontermdef { font-style: italic; font-family: serif; }
span.emph { font-style: italic; }
span.techterm { font-style: italic; }
span.mathit { font-style: italic; }
span.mathsf { font-family: sans-serif; }
span.mathrm { font-family: serif; font-style: normal; }
span.textrm { font-family: serif; }
span.textsl { font-style: italic; }
span.mathtt { font-family: monospace; font-style: normal; }
span.mbox { font-family: serif; font-style: normal; }
span.ungap { display: inline-block; width: 2pt; }
span.textit { font-style: italic; }
span.texttt { font-family: monospace; }
span.tcode_in_codeblock { font-family: monospace; font-style: normal; }
span.phantom { color: white; }

span.math { font-style: normal; }
span.mathblock {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 1.2em;
margin-bottom: 1.2em;
text-align: center;
}
span.mathalpha {
font-style: italic;
}
span.synopsis {
font-weight: bold;
margin-top: 0.5em;
display: block;
}
span.definition {
font-weight: bold;
display: block;
}
.codeblock {
margin-left: 1.2em;
line-height: 127%;
}
.outputblock {
margin-left: 1.2em;
line-height: 127%;
}
div.itemdecl {
margin-top: 2ex;
}
code.itemdeclcode {
white-space: pre;
display: block;
}
span.textsuperscript {
vertical-align: super;
font-size: smaller;
line-height: 0;
}
.footnotenum { vertical-align: super; font-size: smaller; line-height: 0; }
.footnote {
font-size: small;
margin-left: 2em;
margin-right: 2em;
margin-top: 0.6em;
margin-bottom: 0.6em;
}
div.minipage {
display: inline-block;
margin-right: 3em;
}
div.numberedTable {
text-align: center;
margin: 2em;
}
div.figure {
text-align: center;
margin: 2em;
}
table {
border: 1px solid black;
border-collapse: collapse;
margin-left: auto;
margin-right: auto;
margin-top: 0.8em;
text-align: left;
hyphens: none; 
}
td, th {
padding-left: 1em;
padding-right: 1em;
vertical-align: top;
}
td.empty {
padding: 0px;
padding-left: 1px;
}
td.left {
text-align: left;
}
td.right {
text-align: right;
}
td.center {
text-align: center;
}
td.justify {
text-align: justify;
}
td.border {
border-left: 1px solid black;
}
tr.rowsep, td.cline {
border-top: 1px solid black;
}
tr.even, tr.odd {
border-bottom: 1px solid black;
}
tr.capsep {
border-top: 3px solid black;
border-top-style: double;
}
tr.header {
border-bottom: 3px solid black;
border-bottom-style: double;
}
th {
border-bottom: 1px solid black;
}
span.centry {
font-weight: bold;
}
div.table {
display: block;
margin-left: auto;
margin-right: auto;
text-align: center;
width: 90%;
}
span.indented {
display: block;
margin-left: 2em;
margin-bottom: 1em;
margin-top: 1em;
}
ol.enumeratea { list-style-type: none; background: inherit; }
ol.enumerate { list-style-type: none; background: inherit; }

code.sourceCode > span { display: inline; }
</style>
  <link href="data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center">Better lookups for
<code class="sourceCode default">map</code> and
<code class="sourceCode default">unordered_map</code></h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3091R0</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td><!-- $TimeStamp$ -->
2024-02-06 10:36 EST<!-- $ --></td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      LEWGI<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Pablo Halpern<br>&lt;<a href="mailto:phalpern@halpernwightsoftware.com" class="email">phalpern@halpernwightsoftware.com</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#abstract" id="toc-abstract"><span class="toc-section-number">1</span> Abstract<span></span></a></li>
<li><a href="#motivation" id="toc-motivation"><span class="toc-section-number">2</span> Motivation<span></span></a></li>
<li><a href="#proposed-feature" id="toc-proposed-feature"><span class="toc-section-number">3</span> Proposed feature<span></span></a>
<ul>
<li><a href="#overview" id="toc-overview"><span class="toc-section-number">3.1</span> Overview<span></span></a></li>
<li><a href="#the-get-member-function" id="toc-the-get-member-function"><span class="toc-section-number">3.2</span> The
<code class="sourceCode default">get</code> member
function<span></span></a></li>
<li><a href="#the-get_ref-member-function" id="toc-the-get_ref-member-function"><span class="toc-section-number">3.3</span> The
<code class="sourceCode default">get_ref</code> member
function<span></span></a></li>
<li><a href="#the-get_as-member-function" id="toc-the-get_as-member-function"><span class="toc-section-number">3.4</span> The
<code class="sourceCode default">get_as</code> member
function<span></span></a></li>
</ul></li>
<li><a href="#beforeafter-comparisons" id="toc-beforeafter-comparisons"><span class="toc-section-number">4</span> Before/After
Comparisons<span></span></a></li>
<li><a href="#alternatives-considered" id="toc-alternatives-considered"><span class="toc-section-number">5</span> Alternatives
considered<span></span></a>
<ul>
<li><a href="#names" id="toc-names"><span class="toc-section-number">5.1</span> Names<span></span></a></li>
<li><a href="#return-optional-or-expected" id="toc-return-optional-or-expected"><span class="toc-section-number">5.2</span> Return
<code class="sourceCode default">optional</code> or
<code class="sourceCode default">expected</code><span></span></a></li>
<li><a href="#combining-get-and-get_ref-into-a-single-function" id="toc-combining-get-and-get_ref-into-a-single-function"><span class="toc-section-number">5.3</span> Combining
<code class="sourceCode default">get</code> and
<code class="sourceCode default">get_ref</code> into a single
function<span></span></a></li>
<li><a href="#using-get_asmapped_type-instead-of-get_ref" id="toc-using-get_asmapped_type-instead-of-get_ref"><span class="toc-section-number">5.4</span> Using
<code class="sourceCode default">get_as&lt;mapped_type&amp;&gt;</code>
instead of
<code class="sourceCode default">get_ref</code><span></span></a></li>
<li><a href="#rvalue-overloads" id="toc-rvalue-overloads"><span class="toc-section-number">5.5</span> Rvalue
overloads<span></span></a></li>
<li><a href="#free-functions-instead-of-members" id="toc-free-functions-instead-of-members"><span class="toc-section-number">5.6</span> Free functions instead of
members<span></span></a></li>
</ul></li>
<li><a href="#implementation-experience" id="toc-implementation-experience"><span class="toc-section-number">6</span> Implementation
Experience<span></span></a></li>
<li><a href="#wording" id="toc-wording"><span class="toc-section-number">7</span> Wording<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">8</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" id="abstract"><span class="header-section-number">1</span> Abstract<a href="#abstract" class="self-link"></a></h1>
<blockquote>
<p>The most convenient way to look up an element of a
<code class="sourceCode default">map</code> or
<code class="sourceCode default">unordered_map</code> is to use the
index operator, i.e.,
<code class="sourceCode default">theMap[key]</code>. This operator has a
number of limitations, however: 1) it does not work for
<code class="sourceCode default">const</code> containers, 2) it does not
work if the mapped type is not default-constructible, 3) it modifies the
container if the key is not found 4) a default-constructed value is not
always the desired value when the key is not found. These limitations
often require that the user resort to using the
<code class="sourceCode default">find</code> member function, which
returns an iterator that points to a
<code class="sourceCode default">pair</code> and typically leads to more
complex code having at least one
<code class="sourceCode default">if</code> statement and/or duplicate
lookup operations. This paper take inspiration from other languages,
especially Python, and proposes three simple member functions
(<code class="sourceCode default">get</code>,
<code class="sourceCode default">get_ref</code>, and
<code class="sourceCode default">get_as</code>) that simplify lookups
for <code class="sourceCode default">map</code> and
<code class="sourceCode default">unordered_map</code> in situations
where the index operator is suboptimal.</p>
</blockquote>
<h1 data-number="2" id="motivation"><span class="header-section-number">2</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p>Just about every modern computer language has, as part of the
language or its standard library, one or more associative containers
that uniquely associates a key with a mapped value, variously called
<code class="sourceCode default">map</code>,
<code class="sourceCode default">hash_map</code>,
<code class="sourceCode default">dictionary</code>, or something
similar. In C++ we have
<code class="sourceCode default">std::map</code>,
<code class="sourceCode default">std::unordered_map</code>, and
eventually (per <span class="citation" data-cites="P0429R9">[<a href="#ref-P0429R9" role="doc-biblioref">P0429R9</a>]</span> and <span class="citation" data-cites="P2767R2">[<a href="#ref-P2767R2" role="doc-biblioref">P2767R2</a>]</span>)
<code class="sourceCode default">std::flat_map</code>. The easy-to-write
and easy-to-read expression for getting a value for an associated key is
simply, <code class="sourceCode default">theMap[key]</code>; in other
words, a mapped value is retrieved (and often set) using the index
operator, which returns a reference to the value associated with the
key. Unfortunately, the index operator in the C++ associative containers
has a number of shortcomings compared to many other languages:</p>
<ul>
<li>It works only for non-<code class="sourceCode default">const</code>
containers.</li>
<li>It works only for default-constructible mapped types</li>
<li>The default-constructed object (when available) is not always the
correct identity for a given use case.</li>
<li>It modifies the container when the key is absent.</li>
</ul>
<p>Consider a <code class="sourceCode default">std::map</code> named
<code class="sourceCode default">theMap</code>, that maps an integer key
to a floating-point value, modeling a sparse array of
<code class="sourceCode default">double</code>. If we want to find the
largest of the <code class="sourceCode default">double</code> values
mapped to the integer keys in the range 1 to 100, we might be tempted to
write the following loop:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span> largest <span class="op">=</span> <span class="op">-</span>std<span class="op">::</span>numeric_limits<span class="op">&lt;</span><span class="dt">double</span><span class="op">&gt;::</span>infinity<span class="op">()</span>;</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">1</span>; i <span class="op">&lt;=</span> <span class="dv">100</span>; <span class="op">++</span>i<span class="op">)</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  largest <span class="op">=</span> std<span class="op">::</span>max<span class="op">(</span>largest, theMap<span class="op">[</span>i<span class="op">])</span>;</span></code></pre></div>
<p>If <code class="sourceCode default">theMap</code> is
<code class="sourceCode default">const</code>, the loop will not
compile. If any of the keys in the range
<code class="sourceCode default">[1, 100]</code> are absent from the
map, then <code class="sourceCode default">theMap[i]</code> will return
a default-constructed <code class="sourceCode default">double</code>
having value 0.0, which might or might not be desirable, depending on
whether we want to treat missing values as truly having value 0.0 or
whether they should be ignored (or, equivalently, treated as having
value <em>-INF</em>). Finally if, before executing this loop,
<code class="sourceCode default">theMap</code> contains only, say, 5
entries, at the end of the loop it will contain at least 100 entries,
most of which will have zero values.</p>
<p>There are alternatives that avoid all of these shortcomings, but the
alternatives are significantly less elegant, and therefore more error
prone. For example, the <code class="sourceCode default">at</code>
member function looks a lot like
<code class="sourceCode default">operator[]</code> and has none of the
above shortcomings, but missing keys are handled by throwing exceptions,
making it impractical for situations other than when the key is almost
certain to exist. Moreover, a
<code class="sourceCode default">try</code>-<code class="sourceCode default">catch</code>
block within a loop is rarely a clean way to structure code:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span> largest <span class="op">=</span> <span class="op">-</span>std<span class="op">::</span>numeric_limits<span class="op">&lt;</span><span class="dt">double</span><span class="op">&gt;::</span>infinity<span class="op">()</span>;</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">1</span>; i <span class="op">&lt;=</span> <span class="dv">100</span>; <span class="op">++</span>i<span class="op">)</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    largest <span class="op">=</span> std<span class="op">::</span>max<span class="op">(</span>largest, theMap<span class="op">.</span>at<span class="op">(</span>i<span class="op">))</span>;</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span><span class="kw">const</span> std<span class="op">::</span>out_of_range<span class="op">&amp;)</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The above code would work with a
<code class="sourceCode default">const</code> map, would ignore missing
elements (rather than treating them as zeros), and would not populate
the map with useless entries, but many would argue that the loop is
inelegant, at best. In most C++ implementations, it would be extremely
inefficient unless key misses are rare.</p>
<p>The other obvious alternative uses the
<code class="sourceCode default">find</code> member function:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span> largest <span class="op">=</span> <span class="op">-</span>std<span class="op">::</span>numeric_limits<span class="op">&lt;</span><span class="dt">double</span><span class="op">&gt;::</span>infinity<span class="op">()</span>;</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">1</span>; i <span class="op">&lt;=</span> <span class="dv">100</span>; <span class="op">++</span>i<span class="op">)</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> iter <span class="op">=</span> theMap<span class="op">.</span>find<span class="op">(</span>i<span class="op">)</span>;</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>iter <span class="op">!=</span> theMap<span class="op">.</span>end<span class="op">())</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    largest <span class="op">=</span> std<span class="op">::</span>max<span class="op">(</span>largest, iter<span class="op">-&gt;</span>second<span class="op">)</span>;</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This version of the loop is only slightly more verbose than our
starting point and avoids all of the issues, but the use of iterators,
the need to call <em>two</em> member functions
(<code class="sourceCode default">find</code> and
<code class="sourceCode default">end</code>), and having to extract the
<code class="sourceCode default">second</code> element of the element
pair for what should be a <em>simple</em> operation increases the
cognitive load on both the programmer and the reader. Moreover, a
generic use of <code class="sourceCode default">find</code> can yield a
subtle bug. Consider function template
<code class="sourceCode default">f</code>:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Key, <span class="kw">class</span> Value<span class="op">&gt;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span><span class="kw">const</span> Key<span class="op">&amp;</span> k, <span class="kw">const</span> std<span class="op">::</span>map<span class="op">&lt;</span>Key, Value<span class="op">&gt;&amp;</span> aMap<span class="op">)</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  Value obj <span class="op">=</span> <em>some-default-obj-value-expression</em>;</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> iter <span class="op">=</span> aMap<span class="op">.</span>find<span class="op">(</span>k<span class="op">)</span>;</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="op">(</span>iter <span class="op">!=</span> aMap<span class="op">.</span>end<span class="op">())</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    obj <span class="op">=</span> iter<span class="op">-&gt;</span>second;</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// code that uses `obj` ...</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The above code will not compile unless
<code class="sourceCode default">Value</code> is copy-assignable. Worse,
unless tested with a non-assignable type, the bug could go undetected
for a long time. One fix would be initialize
<code class="sourceCode default">obj</code> in a single expression:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>Value obj <span class="op">=</span> aMap<span class="op">.</span>count<span class="op">(</span>k<span class="op">)</span> <span class="op">?</span> aMap<span class="op">.</span>at<span class="op">(</span>k<span class="op">)</span> <span class="op">:</span> <em>some-default-obj-value-expression</em>;</span></code></pre></div>
<p>While correct, this solution involves two lookup operations: One for
the <code class="sourceCode default">count</code> and one for the
<code class="sourceCode default">at</code>. A better fix requires a bit
more code:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> iter <span class="op">=</span> aMap<span class="op">.</span>find<span class="op">(</span>k<span class="op">)</span>;</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>Value obj <span class="op">=</span> iter <span class="op">!=</span> aMap<span class="op">.</span>end<span class="op">()</span> <span class="op">?</span> iter<span class="op">-&gt;</span>second <span class="op">:</span> <em>some-default-obj-value-expression</em>;</span></code></pre></div>
<p>Note that the last solution again involves
<code class="sourceCode default">iterator</code>,
<code class="sourceCode default">pair</code>, and a conditional
expression, which is a far cry from the simplicity of
<code class="sourceCode default">operator[]</code>.</p>
<h1 data-number="3" id="proposed-feature"><span class="header-section-number">3</span> Proposed feature<a href="#proposed-feature" class="self-link"></a></h1>
<h2 data-number="3.1" id="overview"><span class="header-section-number">3.1</span> Overview<a href="#overview" class="self-link"></a></h2>
<p>What’s desired is a simple member function that, given a key, returns
the mapped value if the key exists and a specified <em>alternative</em>
if the value does not exist. Inspired by a similar member of Python
dictionaries, I propose a <code class="sourceCode default">get</code>
member function and related
<code class="sourceCode default">get_ref</code> and
<code class="sourceCode default">get_as&lt;T&gt;</code> member functions
for all C++ dictionary-like associative containers. A slightly
simplified version of set of the proposed prototypes is:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Return by value</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  mapped_type get<span class="op">(</span><span class="kw">const</span> key_type<span class="op">&amp;</span> key, Args<span class="op">&amp;&amp;...</span> args<span class="op">)</span> <span class="kw">const</span>;</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="co">// Return by reference</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Arg<span class="op">&gt;</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>  common_reference_t<span class="op">&lt;</span>mapped_type<span class="op">&amp;</span>,       Arg<span class="op">&amp;&gt;</span> get_ref<span class="op">(</span><span class="kw">const</span> key_type<span class="op">&amp;</span> key, Arg<span class="op">&amp;</span> ref<span class="op">)</span>;</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Arg<span class="op">&gt;</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>  common_reference_t<span class="op">&lt;</span><span class="kw">const</span> mapped_type<span class="op">&amp;</span>, Arg<span class="op">&amp;&gt;</span> get_ref<span class="op">(</span><span class="kw">const</span> key_type<span class="op">&amp;</span> key, Arg<span class="op">&amp;</span> ref<span class="op">)</span> <span class="kw">const</span>;</span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a><span class="co">// Return as a specific type</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> R, <span class="kw">class</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a>  R get_as<span class="op">(</span><span class="kw">const</span> key_type<span class="op">&amp;</span> key, Args<span class="op">&amp;&amp;...</span> args<span class="op">)</span>;</span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> R, <span class="kw">class</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a>  R get_as<span class="op">(</span><span class="kw">const</span> key_type<span class="op">&amp;</span> key, Args<span class="op">&amp;&amp;...</span> args<span class="op">)</span> <span class="kw">const</span>;</span></code></pre></div>
<p>In each case, if <code class="sourceCode default">key</code> is
found, the corresponding mapped value is returned, otherwise, an
alternative return value is constructed from the remaining arguments.
The differences among the proposed member functions are in the way that
the return types are determined.</p>
<h2 data-number="3.2" id="the-get-member-function"><span class="header-section-number">3.2</span> The
<code class="sourceCode default">get</code> member function<a href="#the-get-member-function" class="self-link"></a></h2>
<p>The proposed <code class="sourceCode default">get</code> member is
the simplest to use and is suitable for types having relatively
inexpensive copy constructors. If the key is found, the return value is
a <em>copy</em> of the mapped value, otherwise the return value is
constructed from <code class="sourceCode default">args</code>. If the
key is not found and <code class="sourceCode default">args</code> is an
empty pack, then the return value is default constructed.</p>
<p>Returning by value is not as expensive as it once was because the
materialization rules (formerly <em>copy elision</em> rules) mean that
fewer temporaries are created. Moreover, returning by value allows the
alternative value to be specified as a prvalue such as the literal
<code class="sourceCode default">-1</code> or
<code class="sourceCode default">nullptr</code>.</p>
<h2 data-number="3.3" id="the-get_ref-member-function"><span class="header-section-number">3.3</span> The
<code class="sourceCode default">get_ref</code> member function<a href="#the-get_ref-member-function" class="self-link"></a></h2>
<p>Sometimes returning a reference to the mapped item is desirable,
either for efficiency (to avoid an expensive copy constructor) or
functionality (if you want to modify the item or inspect its address).
The <code class="sourceCode default">get_ref</code> member provides the
necessary functionality. Consider an example where we modify mapped
values through the reference returned from
<code class="sourceCode default">get_ref</code>:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>map<span class="op">&lt;</span>std<span class="op">::</span>string, <span class="dt">int</span><span class="op">&gt;</span> theMap;</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="co">// Increment the entries matching `names`, but only if they are already in `theMap`.</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> <span class="op">(</span><span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> name <span class="op">:</span> names<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> temp <span class="op">=</span> <span class="dv">0</span>;  <span class="co">// Value is irrelevant</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">++</span>theMap<span class="op">.</span>get_ref<span class="op">(</span>name, temp<span class="op">)</span>;  <span class="co">// increment through reference</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Possibly-modified value of `temp` is discarded here.</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Note that the second argument to
<code class="sourceCode default">get_ref</code> must be a single lvalue,
in this case a local variable that will be discarded whether or not it
is modified.</p>
<p>The function’s interface is designed to avoid accidentally binding an
rvalue to a <code class="sourceCode default">const</code> reference
argument, even when the map is
<code class="sourceCode default">const</code>. For example, the
temporary object created when converting a string literal argument to
<code class="sourceCode default">std::string</code> would go out of
scope before <code class="sourceCode default">ref</code> goes out of
scope (lifetime extension is not transitive). The interface is designed
so that this error will be caught at compile time:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span><span class="kw">const</span> std<span class="op">::</span>map<span class="op">&lt;</span><span class="dt">int</span>, std<span class="op">::</span>string<span class="op">&gt;&amp;</span> theMap<span class="op">)</span> <span class="op">{</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> std<span class="op">::</span>string<span class="op">&amp;</span> ref <span class="op">=</span> theMap<span class="op">.</span>get_ref<span class="op">(</span><span class="dv">0</span>, <span class="st">&quot;zero&quot;</span><span class="op">)</span>;  <span class="co">// ERROR: temporary `std::string(&quot;zero&quot;)`</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Finally, the return type for
<code class="sourceCode default">get_ref</code> is the <em>common
reference type</em> between
<code class="sourceCode default">mapped_type&amp;</code> (or
<code class="sourceCode default">const mapped_type&amp;</code>) and the
reference passed as the second argument. This definition makes it easy
to generate a meaningful result when mixing cv-qualifications or when
mixing base-class references with derived-class references in a single
call:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> g<span class="op">(</span><span class="kw">const</span> std<span class="op">::</span>map<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">int</span><span class="op">&gt;&amp;</span> theMap<span class="op">)</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> alt <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span><span class="op">&amp;</span> ref <span class="op">=</span> theMap<span class="op">.</span>get_ref<span class="op">(</span>key, alt<span class="op">)</span>;  <span class="co">// `ref` has type `const int&amp;`</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The result of <code class="sourceCode default">get_ref</code> is
<code class="sourceCode default">const</code> if either or both of the
map or alternative reference are
<code class="sourceCode default">const</code>. Thus
<code class="sourceCode default">ref</code> is
<code class="sourceCode default">const</code> in the example above
because <code class="sourceCode default">theMap</code> is a
<code class="sourceCode default">const</code> lvalue, even though
<code class="sourceCode default">alt</code> is non-const. A similar
normalization occurs when mixing base-class and derived-class
references:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>map<span class="op">&lt;</span><span class="dt">int</span>, Derived<span class="op">&gt;</span> theMap;</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>Base alt<span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span><span class="op">&amp;</span> ref <span class="op">=</span> theMap<span class="op">.</span>get_ref<span class="op">(</span>key, alt<span class="op">)</span>;  <span class="co">// `ref` has type `Base&amp;`</span></span></code></pre></div>
<h2 data-number="3.4" id="the-get_as-member-function"><span class="header-section-number">3.4</span> The
<code class="sourceCode default">get_as</code> member function<a href="#the-get_as-member-function" class="self-link"></a></h2>
<p>The <code class="sourceCode default">get_as</code> member allows the
user to specify the desired return type. It is useful when the desired
type is <em>convertible from</em> the mapped type and where a more
efficient construction is possible for the alternative value. A
ubiquitous example is
<code class="sourceCode default">std::string_view</code>, which can be
constructed efficiently from a
<code class="sourceCode default">std::string</code> or a
<code class="sourceCode default">char</code> array. The
<code class="sourceCode default">get_as</code> member allows the
<code class="sourceCode default">mapped_type</code> to be
<code class="sourceCode default">std::string</code> and the alternative
value to be <code class="sourceCode default">char[]</code> without
generating extra temporary values:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>map<span class="op">&lt;</span><span class="dt">int</span>, std<span class="op">::</span>string<span class="op">&gt;</span> theMap;</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>string_view sv <span class="op">=</span> theMap<span class="op">.</span>get_as<span class="op">&lt;</span>std<span class="op">::</span>string_view<span class="op">&gt;(</span>key, <span class="st">&quot;none&quot;</span><span class="op">)</span>;</span></code></pre></div>
<p>The above example creates the resulting
<code class="sourceCode default">std::string_view</code> from either the
<code class="sourceCode default">std::string</code> stored in the map or
the <code class="sourceCode default">const char[5]</code> passed as the
alternative value, without creating an intervening
<code class="sourceCode default">std::string</code>. It would be
inefficient to convert the <code class="sourceCode default">char</code>
array to <code class="sourceCode default">std::string</code> before
converting it to a
<code class="sourceCode default">std::string_view</code> and it would
create lifetime issues:</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="co">// </span><span class="al">BUG</span><span class="co">: Dangling reference converting returned temporary `string` to `string_view`</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>string_view sv <span class="op">=</span> theMap<span class="op">.</span>get<span class="op">(</span>key, <span class="st">&quot;none&quot;</span><span class="op">)</span>;</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="co">// ERROR: cannot bind temporary `string` to `string&amp;` parameter</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>string_view sv <span class="op">=</span> theMap<span class="op">.</span>get_ref<span class="op">(</span>key, <span class="st">&quot;none&quot;</span><span class="op">)</span>;</span></code></pre></div>
<p>If the specified return type is a reference type, then
<code class="sourceCode default">get_as</code> behaves much like
<code class="sourceCode default">get_ref</code> except that the return
type is exactly the specified type, rather than the deduced common
reference type between the map and the alternative argument:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>map<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">int</span><span class="op">&gt;</span> theMap;</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> <span class="dt">int</span> zero <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span><span class="op">&amp;</span> v1 <span class="op">=</span> theMap<span class="op">.</span>get_as<span class="op">&lt;</span><span class="dt">int</span><span class="op">&amp;&gt;(</span><span class="dv">0</span>, zero<span class="op">)</span>;       <span class="co">// ERROR: `const` mismatch</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span><span class="op">&amp;</span> v2 <span class="op">=</span> theMap<span class="op">.</span>get_as<span class="op">&lt;</span><span class="kw">const</span> <span class="dt">int</span><span class="op">&amp;&gt;(</span><span class="dv">0</span>, zero<span class="op">)</span>; <span class="co">// OK</span></span></code></pre></div>
<h1 data-number="4" id="beforeafter-comparisons"><span class="header-section-number">4</span> Before/After Comparisons<a href="#beforeafter-comparisons" class="self-link"></a></h1>
<p>The following tables shows how operations are simplified using the
proposed new member functions. In these examples
<code class="sourceCode default">K</code>,
<code class="sourceCode default">T</code>, and
<code class="sourceCode default">U</code> are object types;
<code class="sourceCode default">m</code> is an object of (possibly
<em>cv-</em>)
<code class="sourceCode default">std::map&lt;K, T&gt;</code>,
<code class="sourceCode default">unordered_map&lt;K, T&gt;</code> or
<code class="sourceCode default">flat_map&lt;K, T&gt;</code>,
<code class="sourceCode default">k</code> is a value compatible with
<code class="sourceCode default">K</code>,
<code class="sourceCode default">v</code> is an lvalue of type (possibly
<em>cv-</em>) <code class="sourceCode default">T</code>, and
<code class="sourceCode default">a1..aN</code> are arguments that can
used to construct an object of type
<code class="sourceCode default">T</code>.</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Before</strong>
</div></th>
<th><div style="text-align:center">
<strong>After/Alternative</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> iter <span class="op">=</span> m<span class="op">.</span>find<span class="op">(</span>k<span class="op">)</span>;</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>T x <span class="op">=</span> iter <span class="op">==</span> m<span class="op">.</span>end<span class="op">()</span> <span class="op">?</span> T<span class="op">{}</span> <span class="op">:</span> iter<span class="op">-&gt;</span>second;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>T x <span class="op">=</span> m<span class="op">.</span>get<span class="op">(</span>k<span class="op">)</span>;</span></code></pre></div>

</div></td>
</tr>
<tr class="even">
<td><div>

<div class="sourceCode" id="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> iter <span class="op">=</span> m<span class="op">.</span>find<span class="op">(</span>k<span class="op">)</span>;</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>T x <span class="op">=</span> iter <span class="op">==</span> m<span class="op">.</span>end<span class="op">()</span> <span class="op">?</span> T<span class="op">{</span>a1<span class="op">...</span>aN<span class="op">}</span> <span class="op">:</span> iter<span class="op">-&gt;</span>second;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>T x <span class="op">=</span> m<span class="op">.</span>get<span class="op">(</span>k, a1<span class="op">...</span>aN<span class="op">)</span>;</span></code></pre></div>

</div></td>
</tr>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb19"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>T v;</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> iter <span class="op">=</span> m<span class="op">.</span>find<span class="op">(</span>k<span class="op">)</span>;</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>T<span class="op">&amp;</span> x <span class="op">=</span> iter <span class="op">==</span> m<span class="op">.</span>end<span class="op">()</span> <span class="op">?</span> v <span class="op">:</span> iter<span class="op">-&gt;</span>second;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a>T v;</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>T<span class="op">&amp;</span> x <span class="op">=</span> m<span class="op">.</span>get_ref<span class="op">(</span>k, v<span class="op">)</span>;</span></code></pre></div>

</div></td>
</tr>
<tr class="even">
<td><div>

<div class="sourceCode" id="cb21"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>map<span class="op">&lt;</span>K, std<span class="op">::</span>vector<span class="op">&lt;</span>U<span class="op">&gt;&gt;</span> m<span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> iter <span class="op">=</span> m<span class="op">.</span>find<span class="op">(</span>k<span class="op">)</span>;</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>span<span class="op">&lt;</span>U<span class="op">&gt;</span> x <span class="op">=</span> iter <span class="op">==</span> m<span class="op">.</span>end<span class="op">()</span> <span class="op">?</span> std<span class="op">::</span>span<span class="op">&lt;</span>U<span class="op">&gt;{}</span> <span class="op">:</span> iter<span class="op">-&gt;</span>second;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb22"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>map<span class="op">&lt;</span>K, std<span class="op">::</span>vector<span class="op">&lt;</span>U<span class="op">&gt;&gt;</span> m<span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>span<span class="op">&lt;</span>U<span class="op">&gt;</span> x <span class="op">=</span> m<span class="op">.</span>get_as<span class="op">&lt;</span>std<span class="op">::</span>span<span class="op">&lt;</span>U<span class="op">&gt;&gt;(</span>k<span class="op">)</span>;</span></code></pre></div>

</div></td>
</tr>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb23"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>map<span class="op">&lt;</span>K, std<span class="op">::</span>vector<span class="op">&lt;</span>U<span class="op">&gt;&gt;</span> m<span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> std<span class="op">::</span>array<span class="op">&lt;</span>U, N<span class="op">&gt;</span> preset<span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> iter <span class="op">=</span> m<span class="op">.</span>find<span class="op">(</span>k<span class="op">)</span>;</span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>span<span class="op">&lt;</span><span class="kw">const</span> U<span class="op">&gt;</span> x <span class="op">=</span> iter <span class="op">==</span> m<span class="op">.</span>end<span class="op">()</span> <span class="op">?</span> std<span class="op">::</span>span<span class="op">&lt;</span><span class="kw">const</span> U<span class="op">&gt;{</span>preset<span class="op">}</span> <span class="op">:</span> iter<span class="op">-&gt;</span>second;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb24"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>map<span class="op">&lt;</span>K, std<span class="op">::</span>vector<span class="op">&lt;</span>U<span class="op">&gt;&gt;</span> m<span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> std<span class="op">::</span>array<span class="op">&lt;</span>U, N<span class="op">&gt;</span> preset<span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>span<span class="op">&lt;</span><span class="kw">const</span> U<span class="op">&gt;</span> x <span class="op">=</span> m<span class="op">.</span>get_as<span class="op">&lt;</span>std<span class="op">::</span>span<span class="op">&lt;</span><span class="kw">const</span> U<span class="op">&gt;&gt;(</span>k, preset<span class="op">)</span>;</span></code></pre></div>

</div></td>
</tr>
<tr class="even">
<td><div>

<div class="sourceCode" id="cb25"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>unordered_map<span class="op">&lt;</span>K, U<span class="op">*&gt;</span> m<span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> iter <span class="op">=</span> m<span class="op">.</span>find<span class="op">(</span>k<span class="op">)</span>;</span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>iter <span class="op">!=</span> m<span class="op">.</span>end<span class="op">())</span> <span class="op">{</span></span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a>  U<span class="op">*</span> p <span class="op">=</span> iter<span class="op">-&gt;</span>second;</span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb26"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>unordered_map<span class="op">&lt;</span>K, U<span class="op">*&gt;</span> m<span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>U<span class="op">*</span> p <span class="op">=</span> m<span class="op">.</span>get<span class="op">(</span>k, <span class="kw">nullptr</span><span class="op">)</span>;</span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>p<span class="op">)</span> <span class="op">{</span></span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb27"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> iter <span class="op">=</span> m<span class="op">.</span>find<span class="op">(</span>k<span class="op">)</span>;</span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>iter <span class="op">!=</span> m<span class="op">.</span>end<span class="op">())</span> <span class="op">{</span></span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a>  T<span class="op">&amp;</span> r <span class="op">=</span> iter<span class="op">-&gt;</span>second;</span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb28"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a>T not_found;</span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>T<span class="op">&amp;</span> r <span class="op">=</span> m<span class="op">.</span>get_ref<span class="op">(</span>k, not_found<span class="op">)</span>;</span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(&amp;</span>r <span class="op">!=</span> <span class="op">&amp;</span>not_found<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<h1 data-number="5" id="alternatives-considered"><span class="header-section-number">5</span> Alternatives considered<a href="#alternatives-considered" class="self-link"></a></h1>
<h2 data-number="5.1" id="names"><span class="header-section-number">5.1</span> Names<a href="#names" class="self-link"></a></h2>
<p>The name <code class="sourceCode default">get</code> is borrowed from
the Python dictionary member of the same name. Other names considered
were <code class="sourceCode default">lookup</code>,
<code class="sourceCode default">lookup_or</code>, and
<code class="sourceCode default">get_or</code>; the latter two follow
the precedent of
<code class="sourceCode default">std::optional&lt;T&gt;::value_or</code>.
The <code class="sourceCode default">get</code> name was selected for
conciseness and familiarity.</p>
<h2 data-number="5.2" id="return-optional-or-expected"><span class="header-section-number">5.2</span> Return
<code class="sourceCode default">optional</code> or
<code class="sourceCode default">expected</code><a href="#return-optional-or-expected" class="self-link"></a></h2>
<p>Some of the deficiencies of
<code class="sourceCode default">operator[]</code> could be addressed by
adding a member function that returns an
<code class="sourceCode default">optional&lt;mapped_type&gt;</code>
object:</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="co">// ALTERNATIVE (not proposed)</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> get<span class="op">(</span><span class="kw">const</span> key_type<span class="op">&amp;</span> k<span class="op">)</span> <span class="kw">const</span> <span class="op">-&gt;</span> optional<span class="op">&lt;</span>mapped_type<span class="op">&gt;</span>;</span></code></pre></div>
<p>Better yet, if <span class="citation" data-cites="P2988R1">[<a href="#ref-P2988R1" role="doc-biblioref">P2988R1</a>]</span> is adopted,
it could return an
<code class="sourceCode default">optional&lt;T&amp;&gt;</code>:</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="co">// ALTERNATIVE (not proposed) with `optional&lt;T&amp;&gt;` per [P2988R1]</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> get<span class="op">(</span><span class="kw">const</span> key_type<span class="op">&amp;</span> k<span class="op">)</span>       <span class="op">-&gt;</span> optional<span class="op">&lt;</span>mapped_type<span class="op">&amp;&gt;</span>;</span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> get<span class="op">(</span><span class="kw">const</span> key_type<span class="op">&amp;</span> k<span class="op">)</span> <span class="kw">const</span> <span class="op">-&gt;</span> optional<span class="op">&lt;</span><span class="kw">const</span> mapped_type<span class="op">&amp;&gt;</span>;</span></code></pre></div>
<p>While this approach solves the issues listed in the motivation
section of this paper, typical use would require an
<code class="sourceCode default">if</code> statement (making it almost
as verbose to use as <code class="sourceCode default">find</code>), or
the use of <code class="sourceCode default">value_or</code>, making it
syntactically similar to, but more complicated, than the proposed
<code class="sourceCode default">get</code> member.</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Returning <code class="sourceCode default">T</code>
(proposed)</strong>
</div></th>
<th><div style="text-align:center">
<strong>Returning
<code class="sourceCode default">optional&lt;T&gt;</code> (not
proposed)</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb31"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a>product <span class="op">*=</span> theMap<span class="op">.</span>get<span class="op">(</span>k, <span class="dv">1</span><span class="op">)</span>;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb32"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a>product <span class="op">*=</span> theMap<span class="op">.</span>get<span class="op">(</span>k<span class="op">).</span>value_or<span class="op">(</span><span class="dv">1</span><span class="op">)</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>In the second column, a call to
<code class="sourceCode default">get</code>, followed by a call to
<code class="sourceCode default">value_or</code> on the returned
<code class="sourceCode default">optional</code> causes the mapped value
to be copied twice: first into the
<code class="sourceCode default">optional</code> value, then again into
the temporary returned by
<code class="sourceCode default">value_or</code>. Even if
<code class="sourceCode default">optional&lt;T&amp;&gt;</code> is
adopted, per <span class="citation" data-cites="P2988R1">[<a href="#ref-P2988R1" role="doc-biblioref">P2988R1</a>]</span>, there
would be no equivalent to
<code class="sourceCode default">get_ref</code> (because <span class="citation" data-cites="P2988R1">[<a href="#ref-P2988R1" role="doc-biblioref">P2988R1</a>]</span> currently has
<code class="sourceCode default">value_or</code> return by value, even
for a reference <code class="sourceCode default">value_type</code>) or
<code class="sourceCode default">get_as</code>. Ultimately, it was
decided that the <code class="sourceCode default">get</code> interface
returning <code class="sourceCode default">optional</code> does not
provide a substantial advantage over the proposed interface, especially
in the absence of optional references.</p>
<h2 data-number="5.3" id="combining-get-and-get_ref-into-a-single-function"><span class="header-section-number">5.3</span> Combining
<code class="sourceCode default">get</code> and
<code class="sourceCode default">get_ref</code> into a single function<a href="#combining-get-and-get_ref-into-a-single-function" class="self-link"></a></h2>
<p>If the <code class="sourceCode default">Args</code> parameter pack
happens to consist of a single lvalue reference that is compatible with
<code class="sourceCode default">mapped_type&amp;</code>, it would be
possible to return a reference instead of a value, obviating
<code class="sourceCode default">get_ref</code> as a separate function.
Such a “simplification” was seen as confusing, especially to a human
reader, who must analyze the code carefully to determine whether
non-const operations on the returned entity might change a value in the
original map.</p>
<h2 data-number="5.4" id="using-get_asmapped_type-instead-of-get_ref"><span class="header-section-number">5.4</span> Using
<code class="sourceCode default">get_as&lt;mapped_type&amp;&gt;</code>
instead of <code class="sourceCode default">get_ref</code><a href="#using-get_asmapped_type-instead-of-get_ref" class="self-link"></a></h2>
<p>During development of the reference implementation for this proposal,
<code class="sourceCode default">get_as</code> was seen as sufficient
for returning a reference to a member object. Trying to use the library
in usage examples turned up some disadvantages, however:</p>
<ul>
<li>It was verbose, especially when
<code class="sourceCode default">const</code> qualifications were
added.</li>
<li>It was tedious getting <code class="sourceCode default">const</code>
qualifications correct when using
non-<code class="sourceCode default">const</code> maps with
<code class="sourceCode default">const</code> alternative values.</li>
</ul>
<p>The introduction of <code class="sourceCode default">get_ref</code>
made the code easier to read and write, which is the point of this
entire paper.</p>
<h2 data-number="5.5" id="rvalue-overloads"><span class="header-section-number">5.5</span> Rvalue overloads<a href="#rvalue-overloads" class="self-link"></a></h2>
<p>I considered adding an rvalue-reference overload for
<code class="sourceCode default">get_ref</code> that would accept rvalue
reference alternative and return an rvalue reference. None of the other
element lookup functions are overloaded in this way, however (e.g.,
<code class="sourceCode default">std::move(m)[k]</code> does not return
an rvalue reference), so an rvalue overload would be novel and
inconsistent. If, in the future,
<code class="sourceCode default">operator[]</code> and
<code class="sourceCode default">at</code> were to be enhanced with
rvalue overloads, then <code class="sourceCode default">get_ref</code>
should be, as well.</p>
<h2 data-number="5.6" id="free-functions-instead-of-members"><span class="header-section-number">5.6</span> Free functions instead of
members<a href="#free-functions-instead-of-members" class="self-link"></a></h2>
<p>It is possible to provide the functionality described in this paper
using namespace-scope functions, without modifying
<code class="sourceCode default">std::map</code> and
<code class="sourceCode default">std::unordered_map</code>:</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Map, <span class="kw">class</span> K, <span class="kw">class</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> Map<span class="op">::</span>mapped_type get<span class="op">(</span>Map<span class="op">&amp;</span> m, <span class="kw">const</span> K<span class="op">&amp;</span> k, Args<span class="op">&amp;&amp;...</span> args<span class="op">)</span>;</span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> x <span class="op">=</span> get<span class="op">(</span>m, k, a1<span class="op">...</span>aN<span class="op">)</span>;</span></code></pre></div>
<p>One benefit to this approach is that the
<code class="sourceCode default">get</code> template can handle any
dictionary type that follows the general formula of
<code class="sourceCode default">std::map</code> (i.e., having a
<code class="sourceCode default">mapped_type</code>, and a
<code class="sourceCode default">find</code> that returns an
<code class="sourceCode default">iterator</code> pointing to a key-value
<code class="sourceCode default">pair</code>). Such an approach has
disadvantages, however:</p>
<ul>
<li>It is less intuitive because it puts
<code class="sourceCode default">get</code> outside of the map
interface.</li>
<li>The short names can cause ADL issues.</li>
</ul>
<p>In the end, it seemed wise to stick to member functions.</p>
<h1 data-number="6" id="implementation-experience"><span class="header-section-number">6</span> Implementation Experience<a href="#implementation-experience" class="self-link"></a></h1>
<p>An implementation, with tests and usage examples, can be found at <a href="https://github.com/phalpern/WG21-halpern/tree/main/P3091-map_lookup">https://github.com/phalpern/WG21-halpern/tree/main/P3091-map_lookup</a>.</p>
<h1 data-number="7" id="wording"><span class="header-section-number">7</span> Wording<a href="#wording" class="self-link"></a></h1>
<p>Changes are relative to the 2023-12-18 working draft, <span class="citation" data-cites="N4971">[<a href="#ref-N4971" role="doc-biblioref">N4971</a>]</span>.</p>
<p>In <span>24.4.4.1
<a href="https://wg21.link/N4971#map.overview">[map.overview]</a><a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></span>/2, insert the
<code class="sourceCode default">get</code>,
<code class="sourceCode default">get_ref</code>, and
<code class="sourceCode default">get_as</code> element-access
members:</p>
<blockquote>
<div class="line-block"><code class="sourceCode default">//</code>
<em><span>24.4.4.3
<a href="https://wg21.link/N4971#map.access">[map.access]</a></span>,
element access</em><br />
<code class="sourceCode default">mapped_type&amp; operator[](const key_type&amp; x);</code><br />
<code class="sourceCode default">mapped_type&amp; operator[](key_type&amp;&amp; x);</code><br />
<code class="sourceCode default">template&lt;class K&gt; mapped_type&amp; operator[](K&amp;&amp; x);</code><br />
<code class="sourceCode default">mapped_type&amp;       at(const key_type&amp; x);</code><br />
<code class="sourceCode default">const mapped_type&amp; at(const key_type&amp; x) const;</code><br />
<code class="sourceCode default">template&lt;class K&gt; mapped_type&amp;       at(const K&amp; x);</code><br />
<code class="sourceCode default">template&lt;class K&gt; const mapped_type&amp; at(const K&amp; x) const;</code></div>
<div class="add" style="color: #006e28">

<div class="line-block"><code class="sourceCode default">template &lt;class... Args&gt; mapped_type get(const key_type&amp; x, Args&amp;&amp;... args) const;</code><br />
<code class="sourceCode default">template &lt;class K, class... Args&gt; mapped_type get(const K&amp; x, Args&amp;&amp;... args) const;</code><br />
<code class="sourceCode default">template &lt;class U&gt;</code><br />
    <code class="sourceCode default">common_reference_t&lt;mapped_type&amp;,       U&amp;&gt; get_ref(const key_type&amp; x, U&amp; ref);</code><br />
<code class="sourceCode default">template &lt;class U&gt;</code><br />
    <code class="sourceCode default">common_reference_t&lt;const mapped_type&amp;, U&amp;&gt; get_ref(const key_type&amp; x, U&amp; ref) const;</code><br />
<code class="sourceCode default">template &lt;class K, class U&gt;</code><br />
    <code class="sourceCode default">common_reference_t&lt;mapped_type&amp;      , U&amp;&gt; get_ref(const K&amp; x, U&amp; ref);</code><br />
<code class="sourceCode default">template &lt;class K, class U&gt;</code><br />
    <code class="sourceCode default">common_reference_t&lt;const mapped_type&amp;, U&amp;&gt; get_ref(const K&amp; x, U&amp; ref) const;</code><br />
<code class="sourceCode default">template &lt;class R, class... Args&gt; R get_as(const key_type&amp; x, Args&amp;&amp;... args);</code><br />
<code class="sourceCode default">template &lt;class R, class... Args&gt; R get_as(const key_type&amp; x, Args&amp;&amp;... args) const;</code><br />
<code class="sourceCode default">template &lt;class R, class K, class... Args&gt; R get_as(const K&amp; x, Args&amp;&amp;... args);</code><br />
<code class="sourceCode default">template &lt;class R, class K, class... Args&gt; R get_as(const K&amp; x, Args&amp;&amp;... args) const;</code></div>

</div>
</blockquote>
<p><strong>Wording question</strong>: In my reference implementation, I
declared all of these functions as
<code class="sourceCode default">[[nodiscard]]</code>, but the standard
currently seems to use that attribute very parsimoniously, mostly (but
not exclusively) in situations where a resource might leak or where a
function returning a result could be confused with a function that
modifies its input. These functions fit neither criteria, should they be
<code class="sourceCode default">[[nodiscard]]</code> or not?</p>
<p>At the end of <span>24.4.4.3
<a href="https://wg21.link/N4971#map.access">[map.access]</a></span>,
add these descriptions:</p>
<div class="add" style="color: #006e28">

<blockquote>
<div class="line-block"><code class="sourceCode default">template &lt;class... Args&gt; mapped_type get(const key_type&amp; x, Args&amp;&amp;... args) const;</code><br />
<code class="sourceCode default">template &lt;class K, class... Args&gt; mapped_type get(const K&amp; x, Args&amp;&amp;... args) const;</code></div>
</blockquote>
<blockquote>
<blockquote>
<p><em>Constraints</em>: For the second overload, the
<em>qualified-id</em>
<code class="sourceCode default">Compare::is_transparent</code> is valid
and denotes a type.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Returns</em>: <code class="sourceCode default">get_as&lt;mapped_type&gt;(x, std::forward&lt;Args&gt;(args)...)</code>.</p>
</blockquote>
</blockquote>
<blockquote>
<div class="line-block"><code class="sourceCode default">template &lt;class U&gt;</code><br />
    <code class="sourceCode default">common_reference_t&lt;mapped_type&amp;,       U&amp;&gt; get_ref(const key_type&amp; x, U&amp; ref);</code><br />
<code class="sourceCode default">template &lt;class U&gt;</code><br />
    <code class="sourceCode default">common_reference_t&lt;const mapped_type&amp;, U&amp;&gt; get_ref(const key_type&amp; x, U&amp; ref) const;</code><br />
<code class="sourceCode default">template &lt;class K, class U&gt;</code><br />
    <code class="sourceCode default">common_reference_t&lt;mapped_type&amp;      , U&amp;&gt; get_ref(const K&amp; x, U&amp; ref);</code><br />
<code class="sourceCode default">template &lt;class K, class U&gt;</code><br />
    <code class="sourceCode default">common_reference_t&lt;const mapped_type&amp;, U&amp;&gt; get_ref(const K&amp; x, U&amp; ref) const;</code></div>
</blockquote>
<blockquote>
<blockquote>
<p><em>Constraints</em>: For the third and fourth overloads, the
<em>qualified-id</em>
<code class="sourceCode default">Compare::is_transparent</code> is valid
and denotes a type.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Mandates</em>:</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<ul>
<li>The expression <code class="sourceCode default">find(x)</code> is
well-formed.</li>
<li>The result type is a reference type.</li>
<li><code class="sourceCode default">find(x)-&gt;second</code> and
<code class="sourceCode default">ref</code> are both convertible to the
result type.</li>
</ul>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Preconditions</em>: The expression
<code class="sourceCode default">find(x)</code> has well-defined
behavior.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Returns</em>:
<code class="sourceCode default">find(x)-&gt;second</code> if
<code class="sourceCode default">find(x) == end()</code> is
<code class="sourceCode default">false</code>, otherwise
<code class="sourceCode default">ref</code>.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Throws</em>: nothing</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Complexity</em>: Logarithmic</p>
</blockquote>
</blockquote>

</div>
<p><strong>Editorial comment</strong>: The last two <em>mandate</em>s
are expressed in English rather than code because to express them in
code would involve a hard-to-read construction like <code class="sourceCode default">is_convertible_v&lt;decltype((find(x)-&gt;second)), common_reference_t&lt;decltype((find(x)-&gt;second)), U&amp;&gt;</code>.
This could be simplified using some “Let <em>CV_MAPPED_TYPE</em> be…”
language if LWG prefers it.</p>
<div class="add" style="color: #006e28">

<blockquote>
<div class="line-block"><code class="sourceCode default">template &lt;class R, class... Args&gt; R get_as(const key_type&amp; x, Args&amp;&amp;... args);</code><br />
<code class="sourceCode default">template &lt;class R, class... Args&gt; R get_as(const key_type&amp; x, Args&amp;&amp;... args) const;</code><br />
<code class="sourceCode default">template &lt;class R, class K, class... Args&gt; R get_as(const K&amp; x, Args&amp;&amp;... args);</code><br />
<code class="sourceCode default">template &lt;class R, class K, class... Args&gt; R get_as(const K&amp; x, Args&amp;&amp;... args) const;</code></div>
</blockquote>
<blockquote>
<blockquote>
<p><em>Constraints</em>: For the third and fourth overloads, the
<em>qualified-id</em>
<code class="sourceCode default">Compare::is_transparent</code> is valid
and denotes a type.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Mandates</em>:</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<ul>
<li>The expression <code class="sourceCode default">find(x)</code> is
well-formed.</li>
<li><code class="sourceCode default">find(x)-&gt;second</code> is
convertible to <code class="sourceCode default">R</code>.</li>
<li><code class="sourceCode default">is_constructible&lt;R, Args...&gt;</code> is
<code class="sourceCode default">true</code>.</li>
<li>If <code class="sourceCode default">R</code> is a reference type,
then <code class="sourceCode default">sizeof...(Args)</code> is
<code class="sourceCode default">1</code> and <code class="sourceCode default">is_lvalue_reference_v&lt;Args...&gt;</code>
is <code class="sourceCode default">true</code>.</li>
</ul>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Preconditions</em>: The expression
<code class="sourceCode default">find(x)</code> has well-defined
behavior.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Returns</em>:
<code class="sourceCode default">find(x)-&gt;second</code> if
<code class="sourceCode default">find(x) == end()</code> is
<code class="sourceCode default">false</code>, otherwise <code class="sourceCode default">R(std::forward&lt;Args&gt;(args)...)</code>.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Throws</em>: nothing unless the result object’s constructor
throws.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Complexity</em>: Logarithmic</p>
</blockquote>
</blockquote>

</div>
<p>In <span>24.5.4.1
<a href="https://wg21.link/N4971#unord.map.overview">[unord.map.overview]</a></span>/3,
insert the <code class="sourceCode default">get</code>,
<code class="sourceCode default">get_ref</code>, and
<code class="sourceCode default">get_as</code> element-access
members:</p>
<blockquote>
<div class="line-block"><code class="sourceCode default">//</code>
<em><span>24.5.4.3
<a href="https://wg21.link/N4971#unord.map.elem">[unord.map.elem]</a></span>,
element access</em><br />
<code class="sourceCode default">mapped_type&amp; operator[](const key_type&amp; x);</code><br />
<code class="sourceCode default">mapped_type&amp; operator[](key_type&amp;&amp; x);</code><br />
<code class="sourceCode default">template&lt;class K&gt; mapped_type&amp; operator[](K&amp;&amp; x);</code><br />
<code class="sourceCode default">mapped_type&amp;       at(const key_type&amp; x);</code><br />
<code class="sourceCode default">const mapped_type&amp; at(const key_type&amp; x) const;</code><br />
<code class="sourceCode default">template&lt;class K&gt; mapped_type&amp;       at(const K&amp; x);</code><br />
<code class="sourceCode default">template&lt;class K&gt; const mapped_type&amp; at(const K&amp; x) const;</code></div>
<div class="add" style="color: #006e28">

<div class="line-block"><code class="sourceCode default">template &lt;class... Args&gt; mapped_type get(const key_type&amp; x, Args&amp;&amp;... args) const;</code><br />
<code class="sourceCode default">template &lt;class K, class... Args&gt; mapped_type get(const K&amp; x, Args&amp;&amp;... args) const;</code><br />
<code class="sourceCode default">template &lt;class U&gt;</code><br />
    <code class="sourceCode default">common_reference_t&lt;mapped_type&amp;,       U&amp;&gt; get_ref(const key_type&amp; x, U&amp; ref);</code><br />
<code class="sourceCode default">template &lt;class U&gt;</code><br />
    <code class="sourceCode default">common_reference_t&lt;const mapped_type&amp;, U&amp;&gt; get_ref(const key_type&amp; x, U&amp; ref) const;</code><br />
<code class="sourceCode default">template &lt;class K, class U&gt;</code><br />
    <code class="sourceCode default">common_reference_t&lt;mapped_type&amp;      , U&amp;&gt; get_ref(const K&amp; x, U&amp; ref);</code><br />
<code class="sourceCode default">template &lt;class K, class U&gt;</code><br />
    <code class="sourceCode default">common_reference_t&lt;const mapped_type&amp;, U&amp;&gt; get_ref(const K&amp; x, U&amp; ref) const;</code><br />
<code class="sourceCode default">template &lt;class R, class... Args&gt; R get_as(const key_type&amp; x, Args&amp;&amp;... args);</code><br />
<code class="sourceCode default">template &lt;class R, class... Args&gt; R get_as(const key_type&amp; x, Args&amp;&amp;... args) const;</code><br />
<code class="sourceCode default">template &lt;class R, class K, class... Args&gt; R get_as(const K&amp; x, Args&amp;&amp;... args);</code><br />
<code class="sourceCode default">template &lt;class R, class K, class... Args&gt; R get_as(const K&amp; x, Args&amp;&amp;... args) const;</code></div>

</div>
</blockquote>
<p>At the end of <span>24.5.4.3
<a href="https://wg21.link/N4971#unord.map.elem">[unord.map.elem]</a></span>,
add these descriptions:</p>
<div class="add" style="color: #006e28">

<blockquote>
<div class="line-block"><code class="sourceCode default">template &lt;class... Args&gt; mapped_type get(const key_type&amp; x, Args&amp;&amp;... args) const;</code><br />
<code class="sourceCode default">template &lt;class K, class... Args&gt; mapped_type get(const K&amp; x, Args&amp;&amp;... args) const;</code></div>
</blockquote>
<blockquote>
<blockquote>
<p><em>Constraints</em>: For the second overload, the
<em>qualified-id</em>s
<code class="sourceCode default">Hash::is_transparent</code> and
<code class="sourceCode default">Pred::is_transparent</code> are valid
and denote types.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Returns</em>: <code class="sourceCode default">get_as&lt;mapped_type&gt;(x, std::forward&lt;Args&gt;(args)...)</code>.</p>
</blockquote>
</blockquote>
<blockquote>
<div class="line-block"><code class="sourceCode default">template &lt;class U&gt;</code><br />
    <code class="sourceCode default">common_reference_t&lt;mapped_type&amp;,       U&amp;&gt; get_ref(const key_type&amp; x, U&amp; ref);</code><br />
<code class="sourceCode default">template &lt;class U&gt;</code><br />
    <code class="sourceCode default">common_reference_t&lt;const mapped_type&amp;, U&amp;&gt; get_ref(const key_type&amp; x, U&amp; ref) const;</code><br />
<code class="sourceCode default">template &lt;class K, class U&gt;</code><br />
    <code class="sourceCode default">common_reference_t&lt;mapped_type&amp;      , U&amp;&gt; get_ref(const K&amp; x, U&amp; ref);</code><br />
<code class="sourceCode default">template &lt;class K, class U&gt;</code><br />
    <code class="sourceCode default">common_reference_t&lt;const mapped_type&amp;, U&amp;&gt; get_ref(const K&amp; x, U&amp; ref) const;</code></div>
</blockquote>
<blockquote>
<blockquote>
<p><em>Constraints</em>: For the third and fourth overloads, the
<em>qualified-id</em>s
<code class="sourceCode default">Hash::is_transparent</code> and
<code class="sourceCode default">Pred::is_transparent</code> are valid
and denote types.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Mandates</em>:</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<ul>
<li>The expression <code class="sourceCode default">find(x)</code> is
well-formed.</li>
<li>The result type is a reference type.</li>
<li><code class="sourceCode default">find(x)-&gt;second</code> and
<code class="sourceCode default">ref</code> are both convertible to the
result type.</li>
</ul>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Preconditions</em>: The expression
<code class="sourceCode default">find(x)</code> has well-defined
behavior.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Returns</em>:
<code class="sourceCode default">find(x)-&gt;second</code> if
<code class="sourceCode default">find(x) == end()</code> is
<code class="sourceCode default">false</code>, otherwise
<code class="sourceCode default">ref</code>.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Throws</em>: nothing</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Complexity</em>: Logarithmic</p>
</blockquote>
</blockquote>
<blockquote>
<div class="line-block"><code class="sourceCode default">template &lt;class R, class... Args&gt; R get_as(const key_type&amp; x, Args&amp;&amp;... args);</code><br />
<code class="sourceCode default">template &lt;class R, class... Args&gt; R get_as(const key_type&amp; x, Args&amp;&amp;... args) const;</code><br />
<code class="sourceCode default">template &lt;class R, class K, class... Args&gt; R get_as(const K&amp; x, Args&amp;&amp;... args);</code><br />
<code class="sourceCode default">template &lt;class R, class K, class... Args&gt; R get_as(const K&amp; x, Args&amp;&amp;... args) const;</code></div>
</blockquote>
<blockquote>
<blockquote>
<p><em>Constraints</em>: For the third and fourth overloads, the
<em>qualified-id</em>s
<code class="sourceCode default">Hash::is_transparent</code> and
<code class="sourceCode default">Pred::is_transparent</code> are valid
and denote types.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Mandates</em>:</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<ul>
<li>The expression <code class="sourceCode default">find(x)</code> is
well-formed.</li>
<li><code class="sourceCode default">find(x)-&gt;second</code> is
convertible to <code class="sourceCode default">R</code>.</li>
<li><code class="sourceCode default">is_constructible&lt;R, Args...&gt;</code> is
<code class="sourceCode default">true</code>.</li>
<li>If <code class="sourceCode default">R</code> is a reference type,
then <code class="sourceCode default">sizeof...(Args)</code> is
<code class="sourceCode default">1</code> and <code class="sourceCode default">is_lvalue_reference_v&lt;Args...&gt;</code>
is <code class="sourceCode default">true</code>.</li>
</ul>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Preconditions</em>: The expression
<code class="sourceCode default">find(x)</code> has well-defined
behavior.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Returns</em>:
<code class="sourceCode default">find(x)-&gt;second</code> if
<code class="sourceCode default">find(x) == end()</code> is
<code class="sourceCode default">false</code>, otherwise <code class="sourceCode default">R(std::forward&lt;Args&gt;(args)...)</code>.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Throws</em>: nothing unless the result object’s constructor
throws.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Complexity</em>: Logarithmic</p>
</blockquote>
</blockquote>

</div>
<h1 data-number="8" id="bibliography"><span class="header-section-number">8</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" role="doc-bibliography">
<div id="ref-N4971" class="csl-entry" role="doc-biblioentry">
[N4971] Thomas Köppe. 2023-12-18. Working Draft, Programming Languages —
C++. <a href="https://wg21.link/n4971"><div class="csl-block">https://wg21.link/n4971</div></a>
</div>
<div id="ref-P0429R9" class="csl-entry" role="doc-biblioentry">
[P0429R9] Zach Laine. 2022-06-17. A Standard flat_map. <a href="https://wg21.link/p0429r9"><div class="csl-block">https://wg21.link/p0429r9</div></a>
</div>
<div id="ref-P2767R2" class="csl-entry" role="doc-biblioentry">
[P2767R2] Arthur O’Dwyer. 2023-12-09. flat_map/flat_set omnibus. <a href="https://wg21.link/p2767r2"><div class="csl-block">https://wg21.link/p2767r2</div></a>
</div>
<div id="ref-P2988R1" class="csl-entry" role="doc-biblioentry">
[P2988R1] Steve Downey, Peter Sommerlad. 2024-01-05.
std::optional&lt;T&amp;&gt;. <a href="https://wg21.link/p2988r1"><div class="csl-block">https://wg21.link/p2988r1</div></a>
</div>
</div>
<section class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>All citations to the Standard are to
working draft N4971 unless otherwise specified.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
</div>
</div>
</body>
</html>
