<!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" />
  <meta name="dcterms.date" content="2020-01-13" />
  <title>Consistency for size() functions</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%;}
  </style>
  <style>
a.sourceLine { display: inline-block; line-height: 1.25; }
a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
a.sourceLine:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode { white-space: pre; position: relative; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
code.sourceCode { white-space: pre-wrap; }
a.sourceLine { text-indent: -1em; padding-left: 1em; }
}
pre.numberSource a.sourceLine
  { position: relative; left: -4em; }
pre.numberSource a.sourceLine::before
  { content: attr(title);
    position: relative; left: -1em; text-align: right; vertical-align: baseline;
    border: none; pointer-events: all; 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 {
a.sourceLine::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;
}
div.wrapper {
max-width: 60em;
margin: auto;
}
ul {
list-style-type: none;
padding-left: 2em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
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;
}
: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; }

div#refs p { padding-left: 32px; text-indent: -32px; }
</style>
  <link href="data:image/vnd.microsoft.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">Consistency for size() functions</h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #: </td>
    <td>P1970R1</td>
  </tr>
  <tr>
    <td>Date: </td>
    <td>2020-01-13</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project: </td>
    <td>Programming Language C++<br>
      Library Working Group<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to: </td>
    <td>
      Hannes Hauswedell<br>&lt;<a href="mailto:h2@fsfe.org" class="email">h2@fsfe.org</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="#history"><span class="toc-section-number">1</span> History<span></span></a><ul>
<li><a href="#r1"><span class="toc-section-number">1.1</span> R1<span></span></a></li>
<li><a href="#r0"><span class="toc-section-number">1.2</span> R0<span></span></a></li>
</ul></li>
<li><a href="#introduction"><span class="toc-section-number">2</span> Introduction<span></span></a></li>
<li><a href="#motivation-and-scope"><span class="toc-section-number">3</span> Motivation and Scope<span></span></a><ul>
<li><a href="#there-is-no-ssize-that-works-for-all-ranges"><span class="toc-section-number">3.1</span> There is no ssize that works for all ranges<span></span></a></li>
<li><a href="#stdssize-should-behave-as-stdrangesssize"><span class="toc-section-number">3.2</span> <code>std::[s]size</code> should behave as <code>std::ranges::[s]size</code><span></span></a></li>
</ul></li>
<li><a href="#impact-on-the-standard"><span class="toc-section-number">4</span> Impact on the standard<span></span></a></li>
<li><a href="#design-decisions"><span class="toc-section-number">5</span> Design decisions<span></span></a></li>
<li><a href="#discussion-after-r0"><span class="toc-section-number">6</span> Discussion (after R0)<span></span></a><ul>
<li><a href="#why-not-remove-stdrangessize-and-give-stdssize-the-same-semantics-but-keeping-them-as-functions-and-not-making-function-objects"><span class="toc-section-number">6.0.1</span> Why not remove <code>std::ranges::size()</code> and give <code>std::[s]size()</code> the same semantics (but keeping them as functions and not making function objects)?<span></span></a></li>
<li><a href="#stdsizer-is-not-a-subset-of-stdrangessizer-right-now-because-the-latter-only-considers-r.size-if-that-returns-something-integer-like-and-the-former-has-no-such-restrictions."><span class="toc-section-number">6.0.2</span> <code>std::size(r)</code> is not a subset of <code>std::ranges::size(r)</code> right now, because the latter only considers <code>r.size()</code> if that returns something <em>integer-like</em> and the former has no such restrictions.<span></span></a></li>
<li><a href="#stdrangesssize-does-not-work-on-those-sized_ranges-that-have-non-stdintegral-size-type."><span class="toc-section-number">6.0.3</span> <code>std::ranges::ssize()</code> does not work on those <code>sized_range</code>s that have non-<code>std::integral</code> size type.<span></span></a></li>
</ul></li>
<li><a href="#wording"><span class="toc-section-number">7</span> Wording<span></span></a></li>
</ul>
</div>
<h1 id="history"><span class="header-section-number">1</span> History<a href="#history" class="self-link"></a></h1>
<h2 id="r1"><span class="header-section-number">1.1</span> R1<a href="#r1" class="self-link"></a></h2>
<p>Clean-up of wording and integration of wording fixes based on new discussion points. The paper body is unchanged, but new discussion points have been added as “Discussion (after R0)”.</p>
<p>It is my understanding that these changes are in LWG’s realm, but I will double-check with LEWG-chair to see if he wants to see this again.</p>
<p>While I think that this paper is important and <em>should</em> make it into C++20, the urgency and implications for breakage are significantly reduced by the new wording, because the behaviour of <code>std::size()</code> and <code>std::ssize()</code> is largely preserved for arguments that are not <code>sized_range</code>s.</p>
<h2 id="r0"><span class="header-section-number">1.2</span> R0<a href="#r0" class="self-link"></a></h2>
<p>Created during Belfast (Fall 2019) in response to DE269.</p>
<h1 id="introduction"><span class="header-section-number">2</span> Introduction<a href="#introduction" class="self-link"></a></h1>
<p>C++17 introduced <code>std::size()</code> and C++20 will introduce <code>std::ssize()</code> and <code>std::ranges::size()</code>. Why do we need three and do they solve all problems in regard to size? After DE269 raised these questions, LEWG requested I write this paper.</p>
<h1 id="motivation-and-scope"><span class="header-section-number">3</span> Motivation and Scope<a href="#motivation-and-scope" class="self-link"></a></h1>
<table>
<thead>
<tr class="header">
<th></th>
<th><div style="text-align:center">
<strong><code>.size()</code></strong>
</div></th>
<th><div style="text-align:center">
<strong><code>.size()</code> or <code>end() - begin()</code></strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>unsigned †</td>
<td><code>std::size()</code></td>
<td><code>std::ranges::size()</code></td>
</tr>
<tr class="even">
<td>signed</td>
<td><code>std::ssize()</code></td>
<td><em>none</em></td>
</tr>
</tbody>
</table>
<p><small>† <em>This can be signed under certain circumstances, but is not for any types in the standard library. Criticism of this was raised in LEWG, but this is independent of everything else and not touched by this paper to reduce last-minute impact.</em></small></p>
<p><code>std::ranges::size()</code> was introduced (also) because it was desired that subtractable iterator-sentinel-pairs should be sufficient for a range to qualify it as a <code>std::ranges::sized_range</code>. This means <code>std::size()</code> will not work on certain sized ranges, but <code>std::ranges::size()</code> will.</p>
<p><code>std::ssize()</code> has been introduced (with some controversy), because there was the desire to have a signed size type that can be used (among other things) in loops and comparisons with signed counter variables. It is defined as <code>std::size()</code> but casts the type to a comparable signed type. This solves the problem but only works on the subset of sized ranges that <code>std::size()</code> works on.</p>
<h2 id="there-is-no-ssize-that-works-for-all-ranges"><span class="header-section-number">3.1</span> There is no ssize that works for all ranges<a href="#there-is-no-ssize-that-works-for-all-ranges" class="self-link"></a></h2>
<p>The first problem and original intent of DE269 is that there is no signed size function that works on all sized ranges, i.e. if the arguments for adding <code>std::ssize()</code> are valid, they imply that we also need <code>std::ranges::ssize()</code> with the semantics of <code>std::ranges::size()</code> and a cast to a signed type.</p>
<p><strong>The current state is inconsistent in regard to signed vs unsigned</strong> (inside <code>std::ranges::</code>).</p>
<p>Solution: add <code>std::ranges::ssize()</code></p>
<h2 id="stdssize-should-behave-as-stdrangesssize"><span class="header-section-number">3.2</span> <code>std::[s]size</code> should behave as <code>std::ranges::[s]size</code><a href="#stdssize-should-behave-as-stdrangesssize" class="self-link"></a></h2>
<p>During discussion in LEWG it was criticised that we have different semantics in the different namespaces at all, i.e. that <strong>the current state is inconsistent in regard to <code>std::</code> vs <code>std::ranges::</code></strong>. Because the types that <code>std::size()</code> applies to is a subset of the types that <code>std::ranges::size()</code> applies to, it was proposed to make them behave the same or even just have two functions instead of three or four.</p>
<p>It also became evident that this subsumption is only true now (before C++20), because, after C++20, ranges can opt-out of <code>std::ranges::size()</code> via <code>disable_sized_range</code> – but not out of <code>std::size()</code>. Thus any fix in this area must happen now.</p>
<p>The most obvious solution would be to have <code>std::size()</code> behave like <code>std::ranges::size()</code>, remove the latter, and have <code>std::ssize()</code> refer to <code>std::size()</code>. This is not possible, however, because <code>std::ranges::size()</code> is a function object and <code>std::size()</code> is a function that is subject to ADL. Replacing the function with a function object will break code that relied on ADL.</p>
<p>Solution: <code>std::size()</code> and <code>std::ssize()</code> are defined as functions that call their counterparts in <code>std::ranges::</code>. This guarantees that if we must have more than two interfaces, at least we only have two different semantics clearly denoted by name (signed vs unsigned).</p>
<h1 id="impact-on-the-standard"><span class="header-section-number">4</span> Impact on the standard<a href="#impact-on-the-standard" class="self-link"></a></h1>
<p>See above why these changes would be breaking after C++20.</p>
<p>See below for wording.</p>
<h1 id="design-decisions"><span class="header-section-number">5</span> Design decisions<a href="#design-decisions" class="self-link"></a></h1>
<p>This is the current proposal:</p>
<table>
<thead>
<tr class="header">
<th></th>
<th><div style="text-align:center">
<strong><code>.size()</code> or <code>end() - begin()</code></strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>unsigned</td>
<td><code>std::size()</code>, <code>std::ranges::size()</code></td>
</tr>
<tr class="even">
<td>signed</td>
<td><code>std::ssize()</code>, <code>std::ranges::ssize()</code></td>
</tr>
</tbody>
</table>
<p>The discussion in LEWG also proposed the following other “solutions”:</p>
<ol type="1">
<li><p><strong>Replace <code>std::[s]size</code> with <code>std::ranges::[s]size</code>.</strong> This doesn’t work because of function VS function object, see above.</p></li>
<li><p><strong>Only add <code>std::ranges::ssize()</code>, don’t touch <code>std::size()</code> and <code>std::ssize()</code>.</strong> Less invasive, but only fixes the first inconsistency.</p></li>
<li><p><strong>Don’t add <code>std::ranges::ssize()</code> and remove <code>std::ssize()</code>.</strong> This creates some consistency with regard to the absence of any signed size function. It doesn’t solve the second inconsistency above.</p></li>
<li><p><strong>Don’t add <code>std::ranges::ssize()</code>, but re-define <code>std::ssize()</code> in terms of <code>std::ranges::size()</code> instead of <code>std::size</code>.</strong> It solves the problem of a lacking ssize for all ranges. However, it increases inconsistency within <code>std::</code>. And it does not solve the second inconsistency.</p></li>
</ol>
<p>If there is no consensus to accept this proposal as a whole, I would still suggest doing option 2. Option3 would be possible, too, but is likely to decrease consensus in plenary.</p>
<h1 id="discussion-after-r0"><span class="header-section-number">6</span> Discussion (after R0)<a href="#discussion-after-r0" class="self-link"></a></h1>
<h3 id="why-not-remove-stdrangessize-and-give-stdssize-the-same-semantics-but-keeping-them-as-functions-and-not-making-function-objects"><span class="header-section-number">6.0.1</span> Why not remove <code>std::ranges::size()</code> and give <code>std::[s]size()</code> the same semantics (but keeping them as functions and not making function objects)?<a href="#why-not-remove-stdrangessize-and-give-stdssize-the-same-semantics-but-keeping-them-as-functions-and-not-making-function-objects" class="self-link"></a></h3>
<p>Possible, but ranges authors want size functions to be function objects. The change would also be quite invasive – because <code>std::ranges::size()</code> appears frequently. It’s too late to detect subtle breakage at this point.</p>
<h3 id="stdsizer-is-not-a-subset-of-stdrangessizer-right-now-because-the-latter-only-considers-r.size-if-that-returns-something-integer-like-and-the-former-has-no-such-restrictions."><span class="header-section-number">6.0.2</span> <code>std::size(r)</code> is not a subset of <code>std::ranges::size(r)</code> right now, because the latter only considers <code>r.size()</code> if that returns something <em>integer-like</em> and the former has no such restrictions.<a href="#stdsizer-is-not-a-subset-of-stdrangessizer-right-now-because-the-latter-only-considers-r.size-if-that-returns-something-integer-like-and-the-former-has-no-such-restrictions." class="self-link"></a></h3>
<p>While I consider it very unlikely that code returns something not <em>integer-like</em> via <code>.size()</code> <strong>and</strong> also depends on exposing it via <code>std::size()</code> (especially since that was just introduced in C++17), changing this would break currently valid C++17 code. As such, I have changed the wording to maintain the current behaviour of <code>std::size()</code> and delegate to <code>std::ranges::size()</code> only for those arguments that are <code>sized_range</code>s (which is most of the arguments likely used). <code>std::ssize()</code> is adapted in a similar way so that it can potentially work on types that are not <code>sized_range</code>s but that <code>std::size()</code> works on.</p>
<p>This change means that adopting this paper after C++20 would still be possible and only “breaking” in the sense that <code>std::ssize()</code> on a <code>sized_range</code> could possibly return a different type in C++23 than it does in C++20.</p>
<h3 id="stdrangesssize-does-not-work-on-those-sized_ranges-that-have-non-stdintegral-size-type."><span class="header-section-number">6.0.3</span> <code>std::ranges::ssize()</code> does not work on those <code>sized_range</code>s that have non-<code>std::integral</code> size type.<a href="#stdrangesssize-does-not-work-on-those-sized_ranges-that-have-non-stdintegral-size-type." class="self-link"></a></h3>
<p>The reason is that <code>static_cast&lt;common_type_t&lt;ptrdiff_t, make_signed_t&lt;decltype(E)&gt;&gt;&gt;</code> is used to transform the type to signed type and this is not guaranteed to be valid for arbitrary <em>integer-like</em> types (that are allowed for <code>sized_range</code>s; in particular <code>iota_view</code>). This shortcoming of R0 was known to the author and discussed briefly in LEWG. It was found that since this shortcoming is already part of the design of the original <code>std::ssize()</code> and can be fixed after C++20, it would not be addressed now.</p>
<p>Casey Carter expressed dissatisfaction with this approach and proposed various resolutions – one of which I have integrated in the current wording. Note that this affects the semantics of <code>std::ranges::ssize()</code> and <code>std::ssize()</code> for <code>sized_range</code>s; but not <code>std::ssize</code>’s fallback solution described above.</p>
<h1 id="wording"><span class="header-section-number">7</span> Wording<a href="#wording" class="self-link"></a></h1>
<p>§23.2 [iterator.synopsis]</p>
<div>
<div class="sourceCode" id="cb1"><pre class="sourceCode diff"><code class="sourceCode diff"><a class="sourceLine" id="cb1-1" title="1"><span class="st">-template&lt;class C&gt; constexpr auto size(const C&amp; c) -&gt; decltype(c.size());</span></a>
<a class="sourceLine" id="cb1-2" title="2"><span class="st">-template&lt;class T, size_t N&gt; constexpr size_t size(const T (&amp;array)[N]) noexcept;</span></a>
<a class="sourceLine" id="cb1-3" title="3"><span class="va">+template &lt;class C&gt; constexpr auto size(C&amp;&amp; c) noexcept(noexcept(c.size()))</span></a>
<a class="sourceLine" id="cb1-4" title="4"><span class="va">+ -&gt; decltype(c.size());</span></a>
<a class="sourceLine" id="cb1-5" title="5"><span class="va">+template &lt;ranges::sized_range C&gt; constexpr auto size(C&amp;&amp; c)</span></a>
<a class="sourceLine" id="cb1-6" title="6"><span class="va">+ noexcept(noexcept(ranges::size(forward&lt;C&gt;(c))))</span></a>
<a class="sourceLine" id="cb1-7" title="7"><span class="va">+ -&gt; decltype(ranges::size(forward&lt;C&gt;(c)));</span></a>
<a class="sourceLine" id="cb1-8" title="8"><span class="st">-template&lt;class C&gt; constexpr auto ssize(const C&amp; c)</span></a>
<a class="sourceLine" id="cb1-9" title="9"><span class="va">+template&lt;class C&gt; constexpr auto ssize(C&amp;&amp; c)</span></a>
<a class="sourceLine" id="cb1-10" title="10"><span class="va">+ noexcept(noexcept(c.size()))</span></a>
<a class="sourceLine" id="cb1-11" title="11">  -&gt; common_type_t&lt;ptrdiff_t, make_signed_t&lt;decltype(c.size())&gt;&gt;;</a>
<a class="sourceLine" id="cb1-12" title="12"><span class="va">+template &lt;ranges::sized_range C&gt; constexpr auto ssize(C&amp;&amp; c)</span></a>
<a class="sourceLine" id="cb1-13" title="13"><span class="va">+ noexcept(noexcept(ranges::ssize(forward&lt;C&gt;(c))))</span></a>
<a class="sourceLine" id="cb1-14" title="14"><span class="va">+ -&gt; decltype(ranges::ssize(forward&lt;C&gt;(c)));</span></a></code></pre></div>
</div>
<p>§23.7 [iterator.range]</p>
<div>
<div class="sourceCode" id="cb2"><pre class="sourceCode diff"><code class="sourceCode diff"><a class="sourceLine" id="cb2-1" title="1"><span class="st">-template&lt;class C&gt; constexpr auto size(const C&amp; c) -&gt; decltype(c.size());</span></a>
<a class="sourceLine" id="cb2-2" title="2"><span class="st">-  Returns: c.size().</span></a>
<a class="sourceLine" id="cb2-3" title="3"><span class="st">-</span></a>
<a class="sourceLine" id="cb2-4" title="4"><span class="st">-template&lt;class T, size_t N&gt; constexpr size_t size(const T (&amp;array)[N]) noexcept;</span></a>
<a class="sourceLine" id="cb2-5" title="5"><span class="st">-  Returns: N.</span></a>
<a class="sourceLine" id="cb2-6" title="6"></a>
<a class="sourceLine" id="cb2-7" title="7"><span class="va">+template &lt;class C&gt; constexpr auto size(C&amp;&amp; c) noexcept(noexcept(c.size()))</span></a>
<a class="sourceLine" id="cb2-8" title="8"><span class="va">+ -&gt; decltype(c.size());</span></a>
<a class="sourceLine" id="cb2-9" title="9"><span class="va">+  Returns: c.size().</span></a>
<a class="sourceLine" id="cb2-10" title="10"><span class="va">+</span></a>
<a class="sourceLine" id="cb2-11" title="11"><span class="va">+template &lt;ranges::sized_range C&gt; constexpr auto size(C&amp;&amp; c)</span></a>
<a class="sourceLine" id="cb2-12" title="12"><span class="va">+ noexcept(noexcept(ranges::size(forward&lt;C&gt;(c))))</span></a>
<a class="sourceLine" id="cb2-13" title="13"><span class="va">+ -&gt; decltype(ranges::size(forward&lt;C&gt;(c)));</span></a>
<a class="sourceLine" id="cb2-14" title="14"><span class="va">+  Returns: ranges::size(forward&lt;C&gt;(c)).</span></a>
<a class="sourceLine" id="cb2-15" title="15"></a>
<a class="sourceLine" id="cb2-16" title="16"><span class="st">-template&lt;class C&gt; constexpr auto ssize(const C&amp; c)</span></a>
<a class="sourceLine" id="cb2-17" title="17"><span class="va">+template&lt;class C&gt; constexpr auto ssize(C&amp;&amp; c)</span></a>
<a class="sourceLine" id="cb2-18" title="18"><span class="va">+ noexcept(noexcept(c.size()))</span></a>
<a class="sourceLine" id="cb2-19" title="19">  -&gt; common_type_t&lt;ptrdiff_t, make_signed_t&lt;decltype(c.size())&gt;&gt;;</a>
<a class="sourceLine" id="cb2-20" title="20">  Returns: static_cast&lt;common_type_t&lt;ptrdiff_t, make_signed_t&lt;decltype(c.size())&gt;&gt;&gt;(c.size())</a>
<a class="sourceLine" id="cb2-21" title="21"></a>
<a class="sourceLine" id="cb2-22" title="22"><span class="st">-template&lt;class T, ptrdiff_t N&gt; constexpr ptrdiff_t ssize(const T (&amp;array)[N]) noexcept;</span></a>
<a class="sourceLine" id="cb2-23" title="23"><span class="st">-Returns: N.</span></a>
<a class="sourceLine" id="cb2-24" title="24"></a>
<a class="sourceLine" id="cb2-25" title="25"><span class="va">+template &lt;ranges::sized_range C&gt; constexpr auto ssize(C&amp;&amp; c)</span></a>
<a class="sourceLine" id="cb2-26" title="26"><span class="va">+ noexcept(noexcept(ranges::ssize(forward&lt;C&gt;(c))))</span></a>
<a class="sourceLine" id="cb2-27" title="27"><span class="va">+ -&gt; decltype(ranges::ssize(forward&lt;C&gt;(c)));</span></a>
<a class="sourceLine" id="cb2-28" title="28"><span class="va">+  Returns: ranges::ssize(forward&lt;C&gt;(c)).</span></a></code></pre></div>
</div>
<p>§24.2 [ranges.syn]</p>
<div>
<div class="sourceCode" id="cb3"><pre class="sourceCode diff"><code class="sourceCode diff"><a class="sourceLine" id="cb3-1" title="1">    inline constexpr unspecified size = unspecified;</a>
<a class="sourceLine" id="cb3-2" title="2"><span class="va">+   inline constexpr unspecified ssize = unspecified;</span></a>
<a class="sourceLine" id="cb3-3" title="3">    inline constexpr unspecified empty = unspecified;</a>
<a class="sourceLine" id="cb3-4" title="4"></a>
<a class="sourceLine" id="cb3-5" title="5">    [...]</a>
<a class="sourceLine" id="cb3-6" title="6"></a>
<a class="sourceLine" id="cb3-7" title="7">Within this clause, for some integer-like type X ([iterator.concept.winc]),</a>
<a class="sourceLine" id="cb3-8" title="8">make-unsigned-like-t(X) denotes make_­unsigned_­t&lt;X&gt; if X is an integer type;</a>
<a class="sourceLine" id="cb3-9" title="9">otherwise, it denotes a corresponding unspecified unsigned-integer-like type</a>
<a class="sourceLine" id="cb3-10" title="10">of the same width as X.</a>
<a class="sourceLine" id="cb3-11" title="11">For an object x of type X, make-unsigned-like(x) is x explicitly converted to</a>
<a class="sourceLine" id="cb3-12" title="12">make-unsigned-like-t(X).</a>
<a class="sourceLine" id="cb3-13" title="13"><span class="va">+ Within this clause, for some integer-like type X ([iterator.concept.winc]),</span></a>
<a class="sourceLine" id="cb3-14" title="14"><span class="va">+make-signed-like-t(X) denotes make_signed_­t&lt;X&gt; if X is an integer type;</span></a>
<a class="sourceLine" id="cb3-15" title="15"><span class="va">+otherwise, it denotes a corresponding unspecified signed-integer-like type</span></a>
<a class="sourceLine" id="cb3-16" title="16"><span class="va">+of the same width as X.</span></a>
<a class="sourceLine" id="cb3-17" title="17"><span class="va">+For an object x of type X, make-signed-like(x) is x explicitly converted to</span></a>
<a class="sourceLine" id="cb3-18" title="18"><span class="va">+make-signed-like-t(X).</span></a></code></pre></div>
</div>
<p>$24.3 [range.access]</p>
<p>Introduce new §24.3.10 [range.prim.ssize] after §24.3.9 [range.prim.size]</p>
<div>
<div class="sourceCode" id="cb4"><pre class="sourceCode diff"><code class="sourceCode diff"><a class="sourceLine" id="cb4-1" title="1"><span class="va">+24.3.10 ranges::ssize</span></a>
<a class="sourceLine" id="cb4-2" title="2"><span class="va">+</span></a>
<a class="sourceLine" id="cb4-3" title="3"><span class="va">+The name ssize denotes a customization point object([customization.point.object]). The</span></a>
<a class="sourceLine" id="cb4-4" title="4"><span class="va">+expression ranges::ssize(E) for some subexpression E is expression-equivalent to:</span></a>
<a class="sourceLine" id="cb4-5" title="5"><span class="va">+make-signed-like(ranges::size(E)).</span></a></code></pre></div>
</div>
</div>
</div>
</body>
</html>
