<!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="2022-08-21" />
  <title>Generic Programming is just Programming</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>
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; }
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 { } /* 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 { } /* 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;
}
:not(pre) > code {
background-color: #f6f8fa;
padding: 2px 4px 2px 4px;
}
div.sourceCode {
padding: 4px;
}
blockquote {
color: #666666;
margin: 0;
padding-left: 1em;
border-left: 0.5em #f2f4f7 solid;
}
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">Generic Programming is just Programming</h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #: </td>
    <td>P2692R0</td>
  </tr>
  <tr>
    <td>Date: </td>
    <td>2022-08-21</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project: </td>
    <td>Programming Language C++<br>
      SG17<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to: </td>
    <td>
      Mihail Naydenov<br>&lt;<a href="mailto:mihailnajdenov@gmail.com" class="email">mihailnajdenov@gmail.com</a>&gt;<br>
    </td>
  </tr>
</table>

</header>
<div style="clear:both">
<section id="abstract" data-number="1">
<h1 data-number="1"><span class="header-section-number">1</span> Abstract<a href="#abstract" class="self-link"></a></h1>
<p>This paper argues, current generic programming strays too much from the promise of being like regular programming, to the point <em>correct</em> generic programming is an expert-only endeavor in what is essentially a new language.</p>
</section>
<section id="motivation" data-number="2">
<h1 data-number="2"><span class="header-section-number">2</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p><em>“Generic Programming is just Programming”</em><br />
B. Stroustrup</p>
<p>Good code is reusable code and reusable code is often parametrized. If the programmer wants to make a piece of code reusable by abstracting away the types, he/she has two options - “simple” or “advanced”:</p>
<p><strong>Original code</strong></p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1"></a><span class="dt">void</span> silly<span class="op">(</span>MyClass<span class="op">&amp;</span> s<span class="op">)</span></span>
<span id="cb1-2"><a href="#cb1-2"></a><span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3"></a>  <span class="kw">using</span> type <span class="op">=</span> MyClass<span class="op">::</span>related_type;</span>
<span id="cb1-4"><a href="#cb1-4"></a>  <span class="co">// ...</span></span>
<span id="cb1-5"><a href="#cb1-5"></a>  <span class="cf">if</span><span class="op">(</span>s<span class="op">.</span>has_something<span class="op">(</span><span class="st">&quot;hello&quot;</span><span class="op">))</span></span>
<span id="cb1-6"><a href="#cb1-6"></a>     s<span class="op">.</span>do_it<span class="op">()</span>;</span>
<span id="cb1-7"><a href="#cb1-7"></a>  <span class="co">// ...</span></span>
<span id="cb1-8"><a href="#cb1-8"></a><span class="op">}</span></span></code></pre></div>
<p><strong>Simple Generic</strong></p>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> S<span class="op">&gt;</span></span>
<span id="cb2-2"><a href="#cb2-2"></a><span class="dt">void</span> silly<span class="op">(</span>S<span class="op">&amp;</span> s<span class="op">)</span></span>
<span id="cb2-3"><a href="#cb2-3"></a><span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4"></a>  <span class="kw">using</span> type <span class="op">=</span> S<span class="op">::</span>related_type;</span>
<span id="cb2-5"><a href="#cb2-5"></a>  <span class="co">// ...</span></span>
<span id="cb2-6"><a href="#cb2-6"></a>  <span class="cf">if</span><span class="op">(</span>s<span class="op">.</span>has_something<span class="op">(</span><span class="st">&quot;hello&quot;</span><span class="op">))</span></span>
<span id="cb2-7"><a href="#cb2-7"></a>     s<span class="op">.</span>do_it<span class="op">()</span>;</span>
<span id="cb2-8"><a href="#cb2-8"></a>  <span class="co">// ...</span></span>
<span id="cb2-9"><a href="#cb2-9"></a><span class="op">}</span></span></code></pre></div>
<p><strong>Advanced Generic</strong></p>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> S<span class="op">&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2"></a><span class="dt">void</span> silly<span class="op">(</span>S<span class="op">&amp;</span> s<span class="op">)</span></span>
<span id="cb3-3"><a href="#cb3-3"></a><span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4"></a>  <span class="kw">using</span> char_type <span class="op">=</span> MyExtensions<span class="op">::</span>traits<span class="op">&lt;</span>S<span class="op">&gt;::</span>related_type;</span>
<span id="cb3-5"><a href="#cb3-5"></a>  <span class="co">// ...</span></span>
<span id="cb3-6"><a href="#cb3-6"></a>  <span class="cf">if</span><span class="op">(</span>MyExtensions<span class="op">::</span>has_something<span class="op">(</span>s, <span class="st">&quot;hello&quot;</span><span class="op">))</span></span>
<span id="cb3-7"><a href="#cb3-7"></a>    MyExtensions<span class="op">::</span>do_it<span class="op">(</span>s<span class="op">)</span>;</span>
<span id="cb3-8"><a href="#cb3-8"></a>  <span class="co">// ...</span></span>
<span id="cb3-9"><a href="#cb3-9"></a><span class="op">}</span></span></code></pre></div>
<p>Let’s start with the good news: With the simple version, <em>we do</em> keep the promise, “generic programming is just programming”! With very little effort (and syntax for that matter) we turned our silly function into a generic function, one that will work with “any type”. In fact, this is <em>so good</em>, that it is, arguably, the de facto standard for 99% of the C++ developers. Every non-expert, non-library-writer most probably <strong>will</strong> write generic code in that manner.</p>
<p>It is all bad news from here on. As we know, the simple version code is not generic <em>enough</em>, in more aspects then one. To go “the extra mile”, make the code “right”, we have to use the advanced approach. Doing so however:</p>
<p><strong>A)</strong> We <strong>must</strong> considerably change how we write the function.<br />
<strong>B)</strong> We fall into a pit of severe problems and heavy compromises (P2279)<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>.</p>
<p>While there are efforts to solve the pressing issues in <strong>B</strong>, it seems <strong>we have accepted the loss of A.</strong><br />
This proposal begs to disagree with that sentiment.</p>
</section>
<section id="problems" data-number="3">
<h1 data-number="3"><span class="header-section-number">3</span> Problems<a href="#problems" class="self-link"></a></h1>
<section id="dichotomy" data-number="3.1">
<h2 data-number="3.1"><span class="header-section-number">3.1</span> Dichotomy<a href="#dichotomy" class="self-link"></a></h2>
<p>First major problem with the status quo is the fact, we have <em>two</em> static polymorphism systems. As mentioned in <strong>Motivation</strong>, the user can choose b/w having it easy, but limited or having it powerful, but hard (developing effort, code changes, learning ramp). Because the second option does all the first one does, it is “better” and “more correct”, but with no natural progression (or discoverability!) b/w the two options there always be a pain-point in a project: “Is it worth it?”. This rises the question:<br />
Is a project doing “simple templates” generic programming an “unprofessional” one?<br />
(Assuming limitations in user experience like the need to use inheritance/wrapping, etc.)</p>
<p>This is an important question.<br />
If the answer is YES, then the simple method is just for people who “don’t get it” or “don’t want to put the effort” (yet?).<br />
If NO, then we have two systems intensionally for reasons like “legacy” and/or “simpler tasks” or something else, we convince ourselves into.</p>
<p>Either way, it is not a great place to be. In practice, most programmers will continue to use simple, “turn on templates” method and the “right” method will be limited to few “library writers”, who <em>really</em> have to cover all cases, and <em>really</em> want it to be easy for the end users.</p>
<p>There is also the question of <strong>teachability</strong>, including for people migrating from other languages.<br />
How <em>exactly</em> one writes (static) generic code in C++ in the end? How can one port a library from another language, what are the language tools? Can an expert in, say, signal processing write good-to-great generic library, without being a C++ expert <em>as well</em>? And even if he/she is a C++ expert, will he/she <em>choose</em> “the right” way, considering barrier of entry for contributions?</p>
</section>
<section id="explicit-type-mapping-in-the-wrong-place" data-number="3.2">
<h2 data-number="3.2"><span class="header-section-number">3.2</span> Explicit type mapping in the wrong place<a href="#explicit-type-mapping-in-the-wrong-place" class="self-link"></a></h2>
<p>Second serious problem is that this new method puts explicit re-mapping calls (of entities to types’s implementation) inside of the function body. This is <em>radically</em> different then most other generic programming, C++ or not. The other two most post popular methods, templates and dynamic polymorphism, both move this mapping outside of the function, delegating it to the class itself in one for or another.<br />
The only other generic method that forces body code change for the purpose of remapping calls is “variant”, but that code change comes naturally as the author wants exactly that, to <em>remove</em> the mapping from the outside world, doing it manually inside the function instead. And even then, the author <em>can</em> use the objects as usual by manually selecting the type first:</p>
<div class="columns">
<div class="column" style="width:50%;">
<p><strong>Verbose variant usage</strong></p>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1"></a><span class="dt">void</span> silly<span class="op">(</span>variant<span class="op">&lt;</span>A,S,D<span class="op">&gt;</span> t<span class="op">)</span></span>
<span id="cb4-2"><a href="#cb4-2"></a><span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3"></a>  <span class="co">// ...</span></span>
<span id="cb4-4"><a href="#cb4-4"></a>  <span class="kw">using</span> V <span class="op">=</span> variant<span class="op">&lt;</span>A,S,D<span class="op">&gt;</span>;</span>
<span id="cb4-5"><a href="#cb4-5"></a>  variant_alternative_t<span class="op">&lt;</span><span class="dv">1</span>, V<span class="op">&gt;::</span>type; <span class="co">// remap back to S </span></span>
<span id="cb4-6"><a href="#cb4-6"></a>  get<span class="op">&lt;</span><span class="dv">1</span><span class="op">&gt;(</span>t<span class="op">).</span>do_this<span class="op">()</span>;               <span class="co">// remap back again to S </span></span>
<span id="cb4-7"><a href="#cb4-7"></a>  get<span class="op">&lt;</span><span class="dv">1</span><span class="op">&gt;(</span>t<span class="op">).</span>do_that<span class="op">()</span>;               <span class="co">// remap back yet again to S </span></span>
<span id="cb4-8"><a href="#cb4-8"></a><span class="op">}</span></span></code></pre></div>
</div><div class="column" style="width:50%;">
<p><strong>Simplified variant usage</strong></p>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1"></a><span class="dt">void</span> silly<span class="op">(</span>variant<span class="op">&lt;</span>A,S,D<span class="op">&gt;</span> s<span class="op">)</span></span>
<span id="cb5-2"><a href="#cb5-2"></a><span class="op">{</span></span>
<span id="cb5-3"><a href="#cb5-3"></a>  <span class="co">// ...</span></span>
<span id="cb5-4"><a href="#cb5-4"></a>  <span class="kw">auto</span> s <span class="op">=</span> get<span class="op">&lt;</span><span class="dv">1</span><span class="op">&gt;(</span>t<span class="op">)</span>;  <span class="co">// remap just once to S </span></span>
<span id="cb5-5"><a href="#cb5-5"></a>  <span class="kw">decltype</span><span class="op">(</span>s<span class="op">)::</span>type; </span>
<span id="cb5-6"><a href="#cb5-6"></a>  s<span class="op">.</span>do_this<span class="op">()</span>;              </span>
<span id="cb5-7"><a href="#cb5-7"></a>  s<span class="op">.</span>do_that<span class="op">()</span>;              </span>
<span id="cb5-8"><a href="#cb5-8"></a><span class="op">}</span></span></code></pre></div>
</div>
</div>
<p>In modern generic programming, however, we are forced to do the mapping on each call:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1"></a><span class="kw">template</span><span class="op">&lt;</span>S_like T<span class="op">&gt;</span></span>
<span id="cb6-2"><a href="#cb6-2"></a><span class="dt">void</span> odd<span class="op">(</span>T t<span class="op">)</span></span>
<span id="cb6-3"><a href="#cb6-3"></a><span class="op">{</span></span>
<span id="cb6-4"><a href="#cb6-4"></a>  <span class="co">// ...</span></span>
<span id="cb6-5"><a href="#cb6-5"></a>  Sness<span class="op">::</span>traits<span class="op">&lt;</span>T<span class="op">&gt;::</span>type; <span class="co">// remap back to S </span></span>
<span id="cb6-6"><a href="#cb6-6"></a>  Sness<span class="op">::</span>do_this<span class="op">(</span>t<span class="op">)</span>;      <span class="co">// remap back again to S </span></span>
<span id="cb6-7"><a href="#cb6-7"></a>  Sness<span class="op">::</span>do_that<span class="op">(</span>t<span class="op">)</span>;      <span class="co">// remap back yet again to S </span></span>
<span id="cb6-8"><a href="#cb6-8"></a><span class="op">}</span></span></code></pre></div>
<p>What makes things infinitely worse is the fact, the mapping <em>itself</em> must first be created by the author! Literally, <em>a library</em> is needed for what the type does. This is quite different from <em>all</em> other generic programming, including in other languages, and different not in a good way. Having a pice of code that needs an accompanying library and then littering it with explicit calls to that machinery, replacing essentially trivial expressions like method calls, is a bad proposition. One will do it only if really has to.</p>
<p>This is not to say, the remapping itself is a bad thing! Quite the contrary, exactly this remapping is what makes the modern generic programming powerful, compared to the basic template. <em>How</em> (requiring a separate library) and <em>where</em> (invoked via explicit call each time, from inside the function) is unattractive, if not <em>weird:</em></p>
<p>From the point of the user, the template argument <em>is</em> the customization point of the function/class. As far as the user is concerned, what the function/class does is customized on the type. Period. What <em>we</em> however mean behind “customization point” is an extra entity, which sits b/w the concrete type and the actual code. Combining these two, it turns out, we have <em><strong>customization point of a customization point!</strong></em> Seeing it from that perspective, it is no wonder, most people will not be bothered with the second layer of indirection.</p>
</section>
<section id="syntax" data-number="3.3">
<h2 data-number="3.3"><span class="header-section-number">3.3</span> Syntax<a href="#syntax" class="self-link"></a></h2>
<p><strong>Verbosity</strong></p>
<p>By lacking singular mapping point for the entire function body people are forced to use explicit full paths into the library objects on each and every access to the objects. Contrasted to all the code elsewhere, generic and not, C++ or not, this is very jarring.</p>
<p><strong>Forced free function call</strong></p>
<p>Not all actions translate well to free functions calls. For some the fit is quite good if not perfect, for example <code>std::swap</code>, <code>execution::connect</code><a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a>, but for some, <em>arguably most</em>, moving to free function is completely unnatural (e.g. all getters and setters like <code>execution::get_scheduler</code>, <code>execution::set_value</code>, etc). Having properties of a type not being expressed as members will never sit well, especially when we have the same ones <em>already</em> as members like <code>get_allocator</code>.</p>
<p>Overall the syntax is “atypical” at best and quite certainly not something the vast majority of programmers (C++ or otherwise) will willingly opt for.</p>
</section>
</section>
<section id="proposal" data-number="4">
<h1 data-number="4"><span class="header-section-number">4</span> Proposal<a href="#proposal" class="self-link"></a></h1>
<p>If we are to use the list from P2279, we should <strong>add</strong>.</p>
<ul>
<li><strong>non-obtrusive</strong></li>
</ul>
<p>Where behind “obtrusive” we mean <em>both</em> verbosity and code style change. Ignoring the obtrusive nature of current state of affairs leads us, again, into developing <em>two</em> generic systems. No matter how much we polish the “advanced” one, if it still requires essentially a rewrite of the original algorithm into something “atypical”, chances are people will continue using the naive, simple to understand, simple to implement and simple to write approach. This is aggravated by the fact, there is a real chance we might not be able to fix all <em>other</em> issues of the current advanced model to the point “the style” being the only downside!</p>
<p><strong>Where all this leaves us</strong></p>
<p>Currently all of the C++ static polymorphism “customization points”, as described in P2279, are <strong>obtrusive</strong>. This is not “a fault” of the solutions, rather a particularity of the current language - one can’t “just” have a non-obtrusive solution, that is <em>also</em> uncompromisingly generic.</p>
<p>With that in mind, if “We need a <em>language</em> mechanism for customization points”, do we really want to actively pursue such a (language) solution that is <em>still</em> obtrusive? If we bite the bullet of changing the language, we better at least try to solve for “Generic Programming is just Programming”, in the hope of making it as easy and attractive as the “simple template” option. Otherwise the “simple template” will always be the <strong>“Worse is Better”</strong> alternative, if not standard.</p>
<hr />
</section>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>We need a language mechanism for customization points: <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2279r0.html">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2279r0.html</a><a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>std::execution: <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2300r1.html">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2300r1.html</a><a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
</div>
</div>
</body>
</html>
