<!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-11-20" />
  <title>Unicode in the Library, Part 1: UTF Transcoding</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: 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; }
</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">Unicode in the Library, Part
1: UTF Transcoding</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2728R0</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2022-11-20</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>
      SG-16 Unicode<br>
      LEWG-I<br>
      LEWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Zach Laine<br>&lt;<a href="mailto:whatwasthataddress@gmail.com" class="email">whatwasthataddress@gmail.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="#motivation" id="toc-motivation"><span class="toc-section-number">1</span> Motivation<span></span></a>
<ul>
<li><a href="#a-note-about-p1629" id="toc-a-note-about-p1629"><span class="toc-section-number">1.1</span> A note about
P1629<span></span></a></li>
</ul></li>
<li><a href="#the-shortest-unicode-primer-imaginable" id="toc-the-shortest-unicode-primer-imaginable"><span class="toc-section-number">2</span> The shortest Unicode primer
imaginable<span></span></a></li>
<li><a href="#use-cases" id="toc-use-cases"><span class="toc-section-number">3</span> Use cases<span></span></a>
<ul>
<li><a href="#case-1-transcode-a-buffer-as-fast-as-possible" id="toc-case-1-transcode-a-buffer-as-fast-as-possible"><span class="toc-section-number">3.1</span> Case 1: Transcode a buffer as fast
as possible<span></span></a></li>
<li><a href="#case-2-transcode-an-object-as-fast-as-possible" id="toc-case-2-transcode-an-object-as-fast-as-possible"><span class="toc-section-number">3.2</span> Case 2: Transcode an object as
fast as possible<span></span></a></li>
<li><a href="#case-3-transcode-an-object-as-conveniently-as-possible" id="toc-case-3-transcode-an-object-as-conveniently-as-possible"><span class="toc-section-number">3.3</span> Case 3: Transcode an object as
conveniently as possible<span></span></a></li>
<li><a href="#case-4-adapt-to-an-existing-iterator-interface-taking-a-different-utf" id="toc-case-4-adapt-to-an-existing-iterator-interface-taking-a-different-utf"><span class="toc-section-number">3.4</span> Case 4: Adapt to an existing
iterator interface taking a different UTF<span></span></a></li>
<li><a href="#case-5-adapt-to-an-existing-range-interface-taking-a-different-utf" id="toc-case-5-adapt-to-an-existing-range-interface-taking-a-different-utf"><span class="toc-section-number">3.5</span> Case 5: Adapt to an existing range
interface taking a different UTF<span></span></a></li>
</ul></li>
<li><a href="#proposed-design" id="toc-proposed-design"><span class="toc-section-number">4</span> Proposed design<span></span></a>
<ul>
<li><a href="#dependencies" id="toc-dependencies"><span class="toc-section-number">4.1</span> Dependencies<span></span></a></li>
<li><a href="#add-concepts-that-describe-parameters-to-transcoding-apis" id="toc-add-concepts-that-describe-parameters-to-transcoding-apis"><span class="toc-section-number">4.2</span> Add concepts that describe
parameters to transcoding APIs<span></span></a></li>
<li><a href="#add-a-standard-null-terminated-sequence-sentinel" id="toc-add-a-standard-null-terminated-sequence-sentinel"><span class="toc-section-number">4.3</span> Add a standard null-terminated
sequence sentinel<span></span></a></li>
<li><a href="#add-constants-and-utility-functions-that-query-the-state-of-utf-sequences-well-formedness-etc." id="toc-add-constants-and-utility-functions-that-query-the-state-of-utf-sequences-well-formedness-etc."><span class="toc-section-number">4.4</span> Add constants and utility
functions that query the state of UTF sequences (well-formedness,
etc.)<span></span></a></li>
<li><a href="#add-transcode-algorithms" id="toc-add-transcode-algorithms"><span class="toc-section-number">4.5</span> Add transcode
algorithms<span></span></a></li>
<li><a href="#add-the-transcoding-iterators" id="toc-add-the-transcoding-iterators"><span class="toc-section-number">4.6</span> Add the transcoding
iterators<span></span></a>
<ul>
<li><a href="#first-the-basic-ones" id="toc-first-the-basic-ones"><span class="toc-section-number">4.6.1</span> First, the basic
ones<span></span></a></li>
<li><a href="#add-out-and-insert-transcoding-iterators" id="toc-add-out-and-insert-transcoding-iterators"><span class="toc-section-number">4.6.2</span> Add out and insert transcoding
iterators<span></span></a></li>
<li><a href="#add-factory-functions-for-all-the-transcoding-iterators" id="toc-add-factory-functions-for-all-the-transcoding-iterators"><span class="toc-section-number">4.6.3</span> Add factory functions for all
the transcoding iterators<span></span></a></li>
</ul></li>
<li><a href="#add-transcoding-views" id="toc-add-transcoding-views"><span class="toc-section-number">4.7</span> Add transcoding
views<span></span></a>
<ul>
<li><a href="#add-the-views-proper" id="toc-add-the-views-proper"><span class="toc-section-number">4.7.1</span> Add the views
proper<span></span></a></li>
<li><a href="#add-as_utfn" id="toc-add-as_utfn"><span class="toc-section-number">4.7.2</span> Add
<code class="sourceCode default">as_utfN()</code><span></span></a></li>
<li><a href="#add-utfn_view-specializations-of-formatter" id="toc-add-utfn_view-specializations-of-formatter"><span class="toc-section-number">4.7.3</span> Add
<code class="sourceCode default">utfN_view</code> specializations of
<code class="sourceCode default">formatter</code><span></span></a></li>
</ul></li>
<li><a href="#add-a-feature-test-macro" id="toc-add-a-feature-test-macro"><span class="toc-section-number">4.8</span> Add a feature test
macro<span></span></a></li>
<li><a href="#design-notes" id="toc-design-notes"><span class="toc-section-number">4.9</span> Design notes<span></span></a>
<ul>
<li><a href="#iterator-unpacking" id="toc-iterator-unpacking"><span class="toc-section-number">4.9.1</span> Iterator
“unpacking”<span></span></a></li>
</ul></li>
</ul></li>
<li><a href="#implementation-experience" id="toc-implementation-experience"><span class="toc-section-number">5</span> Implementation
experience<span></span></a></li>
<li><a href="#performance" id="toc-performance"><span class="toc-section-number">6</span> Performance<span></span></a>
<ul>
<li><a href="#utf-8-to-utf-16" id="toc-utf-8-to-utf-16"><span class="toc-section-number">6.1</span> UTF-8 to
UTF-16<span></span></a></li>
<li><a href="#utf-8-to-utf-32" id="toc-utf-8-to-utf-32"><span class="toc-section-number">6.2</span> UTF-8 to
UTF-32<span></span></a></li>
</ul></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">7</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" id="motivation"><span class="header-section-number">1</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p>Unicode is important to many, many users in everyday software. It is
not exotic or weird. Well, it’s weird, but it’s not weird to see it
used. C and C++ are the only major production languages with essentially
no support for Unicode.</p>
<p>Let’s fix.</p>
<p>To fix, first we start with the most basic representations of strings
in Unicode: UTF. You might get a UTF string from anywhere; on Windows
you often get them from the OS, in UTF-16. In web-adjacent applications,
strings are most commonly in UTF-8. In ASCII-only applications,
everything is in UTF-8, by its definition as a superset of ASCII.</p>
<p>Often, an application needs to switch between UTFs: 8 -&gt; 16, 32
-&gt; 16, etc. In SG-16 we’ve taken to calling such UTF-N -&gt; UTF-M
operations “transcoding”.</p>
<p>I’m proposing interfaces to do transcoding that meet certain design
requirements that I think are important; I hope you’ll agree:</p>
<ul>
<li>Ranges are the future. We should have range-friendly ways of doing
transcoding. This includes support for sentinels and lazy views.</li>
<li>Iterators are the present. We should support generic programming,
whether it is done in terms of pointers, a particular iterator, or an
iterator type specified as a template parameter.</li>
<li>Pointers are important. The fastest transcoding will always be done
in terms of pointers (due to the speed of SIMD operations in
particular). We should support all-pointer-interface transcoding.</li>
<li>Transcoding cannot be a black box; sometimes you need to be able to
find where there is a break in the encoding, or to detect whether a
sequence has any broken encodings in it. We should provide utility
functions that let users investigate these states.</li>
<li>A null-terminated string should not be treated as a special case.
The ubiquity of such strings means that they should be treated as
first-class strings.</li>
<li>It is common to want to view the same text as code points and code
units at different times. It is therefore important that transcoding
iterators have a convenient way to access the underlying sequence of
code units being transcoded.</li>
</ul>
<h2 data-number="1.1" id="a-note-about-p1629"><span class="header-section-number">1.1</span> A note about P1629<a href="#a-note-about-p1629" class="self-link"></a></h2>
<p><span class="citation" data-cites="P1629R1">[<a href="#ref-P1629R1" role="doc-biblioref">P1629R1</a>]</span> from JeanHeyd Meneide is a much
more ambitious proposal that aims to standardize a general-purpose text
encoding conversion mechanism. This proposal is not at odds with P1629;
the two proposals have largely orthogonal aims. This proposal only
concerns itself with UTF interconversions, which is all that is required
for Unicode support. P1629 is concerned with those conversions, plus a
lot more. Accepting both proposals would not cause problems; in fact,
the APIs proposed here could be used to implement parts of the P1629
design.</p>
<h1 data-number="2" id="the-shortest-unicode-primer-imaginable"><span class="header-section-number">2</span> The shortest Unicode primer
imaginable<a href="#the-shortest-unicode-primer-imaginable" class="self-link"></a></h1>
<p>There are multiple encoding types defined in Unicode: UTF-8, UTF-16,
and UTF-32.</p>
<p>A <em>code unit</em> is the lowest-level datum-type in your Unicode
data. Examples are a <code class="sourceCode default">char</code> in
UTF-8 and a <code class="sourceCode default">uint32_t</code> in
UTF-32.</p>
<p>A <em>code point</em> is a 32-bit integral value that represents a
single Unicode value. Examples are U+0041 “A” “LATIN CAPITAL LETTER A”
and U+0308 “¨” “COMBINING DIAERESIS”.</p>
<p>A code point may be consist of multiple code units. For instance, 3
UTF-8 code units in sequence may encode a particular code unit.</p>
<h1 data-number="3" id="use-cases"><span class="header-section-number">3</span> Use cases<a href="#use-cases" class="self-link"></a></h1>
<p>There are several contexts to consider here:</p>
<ul>
<li>Coding convenience, terseness, and clarity.</li>
<li>Performance.</li>
<li>Compatibility with other APIs.</li>
</ul>
<p>Some times the contexts are in alignment, and sometimes they are in
conflict. We need multiple ways to do transcoding to cover all of those
contexts. Let’s make things more concrete:</p>
<h2 data-number="3.1" id="case-1-transcode-a-buffer-as-fast-as-possible"><span class="header-section-number">3.1</span> Case 1: Transcode a buffer as
fast as possible<a href="#case-1-transcode-a-buffer-as-fast-as-possible" class="self-link"></a></h2>
<p>We care primarily about performance in this use case, so everything
is a pointer. Also, our wire-communications layer knows nothing about
the UTFs, so we need to use some of the utility functions to make sure
we don’t process partially-received UTF-8 sequences.</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="co">// Using same size to ensure the transcode operation always has room.</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="dt">char</span> utf8_buf<span class="op">[</span>buf_size<span class="op">]</span>;</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="dt">char</span> utf16_buf<span class="op">[</span>buf_size<span class="op">]</span>;</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="dt">char</span> <span class="op">*</span> read_first <span class="op">=</span> utf8_buf;</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="cf">while</span> <span class="op">(</span><span class="kw">true</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Reads off a wire; may contain partial UTF-8 sequences at the ends of</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">// some reads.</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> <span class="op">*</span> buf_last <span class="op">=</span> read_into_utf8_buffer<span class="op">(</span>read_first, utf8_buf <span class="op">+</span> buf_size<span class="op">)</span>;</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>buf_last <span class="op">==</span> read_first<span class="op">)</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">continue</span>;</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>    <span class="co">// find the last whole UTF-8 sequence, so we don&#39;t feed partial sequences</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    <span class="co">// to the algorithm below.</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> <span class="op">*</span> last <span class="op">=</span> buf_last;</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> <span class="kw">const</span> last_lead <span class="op">=</span> std<span class="op">::</span>ranges<span class="op">::</span>find_last_if<span class="op">(</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>        utf8_buf, buf_last, std<span class="op">::</span>uc<span class="op">::</span>lead_code_unit<span class="op">)</span>;</span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(!</span>last_lead<span class="op">.</span>empty<span class="op">())</span> <span class="op">{</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> <span class="kw">const</span> dist_from_end <span class="op">=</span> buf_last <span class="op">-</span> last_lead<span class="op">.</span>begin<span class="op">()</span>;</span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>        <span class="ot">assert</span><span class="op">(</span>dist_from_end <span class="op">&lt;=</span> <span class="dv">4</span><span class="op">)</span>;</span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>std<span class="op">::</span>uc<span class="op">::</span>utf8_code_units<span class="op">(*</span>last_lead<span class="op">.</span>begin<span class="op">())</span> <span class="op">!=</span> dist_from_end<span class="op">)</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a>            last <span class="op">=</span> last_lead<span class="op">.</span>begin<span class="op">()</span>;</span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Same interface as std::ranges::copy(), except that it converts as it copies.</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> <span class="kw">const</span> result <span class="op">=</span> std<span class="op">::</span>uc<span class="op">::</span>transcode_to_utf16<span class="op">(</span>utf8_buf, last, utf16_buf<span class="op">)</span>;</span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Do something with the resulting UTF-16 buffer contents.</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a>    send_utf16_somewhere<span class="op">(</span>utf16_buf, result<span class="op">.</span>out<span class="op">)</span>;</span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Copy partial UTF-8 sequence to start of buffer.</span></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a>    read_first <span class="op">=</span> std<span class="op">::</span>ranges<span class="op">::</span>copy_backward<span class="op">(</span>last, buf_last, utf8_buf<span class="op">).</span>out;</span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="3.2" id="case-2-transcode-an-object-as-fast-as-possible"><span class="header-section-number">3.2</span> Case 2: Transcode an object as
fast as possible<a href="#case-2-transcode-an-object-as-fast-as-possible" class="self-link"></a></h2>
<p><code class="sourceCode default">my_string</code> does not provide a
pointer-based interface, so we need to use more generic facilities for
this case.</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="kw">struct</span> my_string; <span class="co">// Some string type with *non-pointer* iterators.</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>my_string input <span class="op">=</span> get_utf8_input<span class="op">()</span>;</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">uint16_t</span><span class="op">&gt;</span> input_as_utf16<span class="op">(</span>input<span class="op">.</span>size<span class="op">())</span>; <span class="co">// Reserve some space.</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> <span class="kw">const</span> result <span class="op">=</span> std<span class="op">::</span>uc<span class="op">::</span>transcode_to_utf16<span class="op">(</span>input, input_as_utf16<span class="op">.</span>data<span class="op">())</span>;</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>input_as_utf16<span class="op">.</span>resize<span class="op">(</span>result<span class="op">.</span>out <span class="op">-</span> input_as_utf16<span class="op">.</span>data<span class="op">())</span>; <span class="co">// Trim unused space.</span></span></code></pre></div>
<h2 data-number="3.3" id="case-3-transcode-an-object-as-conveniently-as-possible"><span class="header-section-number">3.3</span> Case 3: Transcode an object as
conveniently as possible<a href="#case-3-transcode-an-object-as-conveniently-as-possible" class="self-link"></a></h2>
<p>This solution is similar to Case 2, but marginally more convenient.
There are other cases, like accepting output from
<code class="sourceCode default">std</code> algorithms, that indicate
use of a back-inserter.</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="kw">struct</span> my_string; <span class="co">// Some string type with *non-pointer* iterators.</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>my_string input <span class="op">=</span> get_utf8_input<span class="op">()</span>;</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">uint16_t</span><span class="op">&gt;</span> input_as_utf16;</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>ranges<span class="op">::</span>copy<span class="op">(</span>input, std<span class="op">::</span>uc<span class="op">::</span>from_utf8_back_inserter<span class="op">(</span>input_as_utf16<span class="op">))</span>;</span></code></pre></div>
<h2 data-number="3.4" id="case-4-adapt-to-an-existing-iterator-interface-taking-a-different-utf"><span class="header-section-number">3.4</span> Case 4: Adapt to an existing
iterator interface taking a different UTF<a href="#case-4-adapt-to-an-existing-iterator-interface-taking-a-different-utf" class="self-link"></a></h2>
<p>This time, we have a generic iterator interface we want to transcode
into, so we want to use the transcoding iterators.</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="co">// A generic function that accepts sequences of UTF-16.</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> UTF16Iter<span class="op">&gt;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> process_input<span class="op">(</span>UTF16Iter first, UTF16Iter last<span class="op">)</span>;</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>string input <span class="op">=</span> get_utf8_input<span class="op">()</span>; <span class="co">// A std::string used as a UTF-8 string.</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>process_input<span class="op">(</span>std<span class="op">::</span>uc<span class="op">::</span>utf_8_to_16_iterator<span class="op">(</span>input<span class="op">.</span>begin<span class="op">()</span>, input<span class="op">.</span>begin<span class="op">()</span>, input<span class="op">.</span>end<span class="op">())</span>,</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>              std<span class="op">::</span>uc<span class="op">::</span>utf_8_to_16_iterator<span class="op">(</span>input<span class="op">.</span>begin<span class="op">()</span>, input<span class="op">.</span>end<span class="op">()</span>, input<span class="op">.</span>end<span class="op">()))</span>;</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="co">// Even more conveniently:</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> <span class="kw">const</span> utf16_view <span class="op">=</span> std<span class="op">::</span>uc<span class="op">::</span>as_utf16<span class="op">(</span>input<span class="op">)</span>;</span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>process_input<span class="op">(</span>utf16_view<span class="op">.</span>begin<span class="op">()</span>, utf16<span class="op">.</span>end<span class="op">())</span>;</span></code></pre></div>
<h2 data-number="3.5" id="case-5-adapt-to-an-existing-range-interface-taking-a-different-utf"><span class="header-section-number">3.5</span> Case 5: Adapt to an existing
range interface taking a different UTF<a href="#case-5-adapt-to-an-existing-range-interface-taking-a-different-utf" class="self-link"></a></h2>
<p>In this case, we have a generic range interface to transcode into, so
we use a transcoding view.</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><span class="co">// A generic function that accepts sequences of UTF-16.</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> UTF16Range<span class="op">&gt;</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> process_input<span class="op">(</span>UTF16Range <span class="op">&amp;&amp;</span> r<span class="op">)</span>;</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>string input <span class="op">=</span> get_utf8_input<span class="op">()</span>; <span class="co">// A std::string used as a UTF-8 string.</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>process_input<span class="op">(</span>std<span class="op">::</span>uc<span class="op">::</span>as_utf16<span class="op">(</span>input<span class="op">))</span>;</span></code></pre></div>
<h1 data-number="4" id="proposed-design"><span class="header-section-number">4</span> Proposed design<a href="#proposed-design" class="self-link"></a></h1>
<h2 data-number="4.1" id="dependencies"><span class="header-section-number">4.1</span> Dependencies<a href="#dependencies" class="self-link"></a></h2>
<p>This proposal depends on the existence of <a href="https://isocpp.org/files/papers/P2727R0.html">P2727</a>
“std::iterator_interface”.</p>
<h2 data-number="4.2" id="add-concepts-that-describe-parameters-to-transcoding-apis"><span class="header-section-number">4.2</span> Add concepts that describe
parameters to transcoding APIs<a href="#add-concepts-that-describe-parameters-to-transcoding-apis" class="self-link"></a></h2>
<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">namespace</span> std<span class="op">::</span>uc <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">enum</span> <span class="kw">class</span> format <span class="op">{</span> utf8 <span class="op">=</span> <span class="dv">1</span>, utf16 <span class="op">=</span> <span class="dv">2</span>, utf32 <span class="op">=</span> <span class="dv">4</span> <span class="op">}</span>;</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, format F<span class="op">&gt;</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> code_unit <span class="op">=</span> integral<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span> <span class="op">==</span> <span class="op">(</span><span class="dt">int</span><span class="op">)</span>F;</span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf8_code_unit <span class="op">=</span> code_unit<span class="op">&lt;</span>T, format<span class="op">::</span>utf8<span class="op">&gt;</span>;</span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf16_code_unit <span class="op">=</span> code_unit<span class="op">&lt;</span>T, format<span class="op">::</span>utf16<span class="op">&gt;</span>;</span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf32_code_unit <span class="op">=</span> code_unit<span class="op">&lt;</span>T, format<span class="op">::</span>utf32<span class="op">&gt;</span>;</span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf_code_unit <span class="op">=</span> utf8_code_unit<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">||</span> utf16_code_unit<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">||</span> utf32_code_unit<span class="op">&lt;</span>T<span class="op">&gt;</span>;</span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, format F<span class="op">&gt;</span></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> code_unit_iter <span class="op">=</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a>      bidirectional_iterator<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> code_unit<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>T<span class="op">&gt;</span>, F<span class="op">&gt;</span>;</span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, format F<span class="op">&gt;</span></span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> code_unit_pointer <span class="op">=</span></span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true" tabindex="-1"></a>      is_pointer_v<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> code_unit<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>T<span class="op">&gt;</span>, F<span class="op">&gt;</span>;</span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, format F<span class="op">&gt;</span></span>
<span id="cb6-27"><a href="#cb6-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> code_unit_range <span class="op">=</span> ranges<span class="op">::</span>bidirectional_range<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb6-28"><a href="#cb6-28" aria-hidden="true" tabindex="-1"></a>      code_unit<span class="op">&lt;</span>ranges<span class="op">::</span>range_value_t<span class="op">&lt;</span>T<span class="op">&gt;</span>, F<span class="op">&gt;</span>;</span>
<span id="cb6-29"><a href="#cb6-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-30"><a href="#cb6-30" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-31"><a href="#cb6-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf8_iter <span class="op">=</span> code_unit_iter<span class="op">&lt;</span>T, format<span class="op">::</span>utf8<span class="op">&gt;</span>;</span>
<span id="cb6-32"><a href="#cb6-32" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-33"><a href="#cb6-33" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf8_pointer <span class="op">=</span> code_unit_pointer<span class="op">&lt;</span>T, format<span class="op">::</span>utf8<span class="op">&gt;</span>;</span>
<span id="cb6-34"><a href="#cb6-34" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-35"><a href="#cb6-35" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf8_range <span class="op">=</span> code_unit_range<span class="op">&lt;</span>T, format<span class="op">::</span>utf8<span class="op">&gt;</span>;</span>
<span id="cb6-36"><a href="#cb6-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-37"><a href="#cb6-37" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-38"><a href="#cb6-38" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf16_iter <span class="op">=</span> code_unit_iter<span class="op">&lt;</span>T, format<span class="op">::</span>utf16<span class="op">&gt;</span>;</span>
<span id="cb6-39"><a href="#cb6-39" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-40"><a href="#cb6-40" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf16_pointer <span class="op">=</span> code_unit_pointer<span class="op">&lt;</span>T, format<span class="op">::</span>utf16<span class="op">&gt;</span>;</span>
<span id="cb6-41"><a href="#cb6-41" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-42"><a href="#cb6-42" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf16_range <span class="op">=</span> code_unit_range<span class="op">&lt;</span>T, format<span class="op">::</span>utf16<span class="op">&gt;</span>;</span>
<span id="cb6-43"><a href="#cb6-43" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-44"><a href="#cb6-44" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-45"><a href="#cb6-45" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf32_iter <span class="op">=</span> code_unit_iter<span class="op">&lt;</span>T, format<span class="op">::</span>utf32<span class="op">&gt;</span>;</span>
<span id="cb6-46"><a href="#cb6-46" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-47"><a href="#cb6-47" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf32_pointer <span class="op">=</span> code_unit_pointer<span class="op">&lt;</span>T, format<span class="op">::</span>utf32<span class="op">&gt;</span>;</span>
<span id="cb6-48"><a href="#cb6-48" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-49"><a href="#cb6-49" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf32_range <span class="op">=</span> code_unit_range<span class="op">&lt;</span>T, format<span class="op">::</span>utf32<span class="op">&gt;</span>;</span>
<span id="cb6-50"><a href="#cb6-50" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-51"><a href="#cb6-51" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-52"><a href="#cb6-52" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf_iter <span class="op">=</span> utf8_iter<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">||</span> utf16_iter<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">||</span> utf32_iter<span class="op">&lt;</span>T<span class="op">&gt;</span>;</span>
<span id="cb6-53"><a href="#cb6-53" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-54"><a href="#cb6-54" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf_pointer <span class="op">=</span> utf8_pointer<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">||</span> utf16_pointer<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">||</span> utf32_pointer<span class="op">&lt;</span>T<span class="op">&gt;</span>;</span>
<span id="cb6-55"><a href="#cb6-55" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-56"><a href="#cb6-56" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf_range <span class="op">=</span> utf8_range<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">||</span> utf16_range<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">||</span> utf32_range<span class="op">&lt;</span>T<span class="op">&gt;</span>;</span>
<span id="cb6-57"><a href="#cb6-57" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-58"><a href="#cb6-58" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-59"><a href="#cb6-59" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf_range_like <span class="op">=</span></span>
<span id="cb6-60"><a href="#cb6-60" aria-hidden="true" tabindex="-1"></a>      utf_range<span class="op">&lt;</span>remove_reference_t<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span> <span class="op">||</span> utf_pointer<span class="op">&lt;</span>remove_reference_t<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span>;</span>
<span id="cb6-61"><a href="#cb6-61" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-62"><a href="#cb6-62" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-63"><a href="#cb6-63" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf8_input_range_like <span class="op">=</span></span>
<span id="cb6-64"><a href="#cb6-64" aria-hidden="true" tabindex="-1"></a>        <span class="op">(</span>ranges<span class="op">::</span>input_range<span class="op">&lt;</span>remove_reference_t<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span> utf8_code_unit<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>T<span class="op">&gt;&gt;)</span> <span class="op">||</span></span>
<span id="cb6-65"><a href="#cb6-65" aria-hidden="true" tabindex="-1"></a>        utf8_pointer<span class="op">&lt;</span>remove_reference_t<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span>;</span>
<span id="cb6-66"><a href="#cb6-66" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-67"><a href="#cb6-67" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf16_input_range_like <span class="op">=</span></span>
<span id="cb6-68"><a href="#cb6-68" aria-hidden="true" tabindex="-1"></a>        <span class="op">(</span>ranges<span class="op">::</span>input_range<span class="op">&lt;</span>remove_reference_t<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span> utf16_code_unit<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>T<span class="op">&gt;&gt;)</span> <span class="op">||</span></span>
<span id="cb6-69"><a href="#cb6-69" aria-hidden="true" tabindex="-1"></a>        utf16_pointer<span class="op">&lt;</span>remove_reference_t<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span>;</span>
<span id="cb6-70"><a href="#cb6-70" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-71"><a href="#cb6-71" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf32_input_range_like <span class="op">=</span></span>
<span id="cb6-72"><a href="#cb6-72" aria-hidden="true" tabindex="-1"></a>        <span class="op">(</span>ranges<span class="op">::</span>input_range<span class="op">&lt;</span>remove_reference_t<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span> utf32_code_unit<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>T<span class="op">&gt;&gt;)</span> <span class="op">||</span></span>
<span id="cb6-73"><a href="#cb6-73" aria-hidden="true" tabindex="-1"></a>        utf32_pointer<span class="op">&lt;</span>remove_reference_t<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span>;</span>
<span id="cb6-74"><a href="#cb6-74" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-75"><a href="#cb6-75" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb6-76"><a href="#cb6-76" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> utf_input_range_like <span class="op">=</span></span>
<span id="cb6-77"><a href="#cb6-77" aria-hidden="true" tabindex="-1"></a>        utf8_input_range_like<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">||</span> utf16_input_range_like<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">||</span> utf32_input_range_like<span class="op">&lt;</span>T<span class="op">&gt;</span>;</span>
<span id="cb6-78"><a href="#cb6-78" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-79"><a href="#cb6-79" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="4.3" id="add-a-standard-null-terminated-sequence-sentinel"><span class="header-section-number">4.3</span> Add a standard null-terminated
sequence sentinel<a href="#add-a-standard-null-terminated-sequence-sentinel" class="self-link"></a></h2>
<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="kw">namespace</span> std<span class="op">::</span>uc <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> null_sentinel_t <span class="op">{</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> null_sentinel_t base<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</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="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> utf8_code_unit<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">||</span> utf16_code_unit<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">||</span> utf32_code_unit<span class="op">&lt;</span>T<span class="op">&gt;</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>T<span class="op">*</span> p, null_sentinel_t<span class="op">)</span>;</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">inline</span> <span class="kw">constexpr</span> null_sentinel_t null_sentinel;</span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The <code class="sourceCode default">base()</code> member bears
explanation. It is there to make iterator/sentinel pairs easy to use in
a generic context. Consider a range
<code class="sourceCode default">r1</code> of code points delimited by a
pair of <code class="sourceCode default">utf_8_to_32_iterator&lt;char const *&gt;</code>
transcoding iterators (defined later in this paper). The range of
underlying UTF-8 code units is
[<code class="sourceCode default">r1.begin().base()</code>,
<code class="sourceCode default">r1.end().base()</code>).</p>
<p>Now consider a range <code class="sourceCode default">r2</code> of
code points that is delimited by a <code class="sourceCode default">utf_8_to_32_iterator&lt;char const *&gt;</code>
transcoding iterator and a
<code class="sourceCode default">null_sentinel</code>. Now our
underlying range of UTF-8 is
[<code class="sourceCode default">r.begin().base()</code>,
<code class="sourceCode default">null_sentinel</code>).</p>
<p>Instead of making people writing generic code have to special-case
the use of <code class="sourceCode default">null_sentinel</code>,
<code class="sourceCode default">null_sentinel</code> has a
<code class="sourceCode default">base()</code> member that lets us write
<code class="sourceCode default">r.end().base()</code> instead of
<code class="sourceCode default">null_sentinel</code>. This means that
for either <code class="sourceCode default">r</code> or
<code class="sourceCode default">r2</code>, the underlying range of
UTF-8 code units is just
[<code class="sourceCode default">r1.begin().base()</code>,
<code class="sourceCode default">r1.end().base()</code>).</p>
<h2 data-number="4.4" id="add-constants-and-utility-functions-that-query-the-state-of-utf-sequences-well-formedness-etc."><span class="header-section-number">4.4</span> Add constants and utility
functions that query the state of UTF sequences (well-formedness,
etc.)<a href="#add-constants-and-utility-functions-that-query-the-state-of-utf-sequences-well-formedness-etc." class="self-link"></a></h2>
<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><span class="kw">namespace</span> std<span class="op">::</span>uc <span class="op">{</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">inline</span> <span class="kw">constexpr</span> <span class="dt">uint16_t</span> high_surrogate_base <span class="op">=</span> <span class="bn">0xd7c0</span>;</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">inline</span> <span class="kw">constexpr</span> <span class="dt">uint16_t</span> low_surrogate_base <span class="op">=</span> <span class="bn">0xdc00</span>;</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">inline</span> <span class="kw">constexpr</span> <span class="dt">uint32_t</span> high_surrogate_min <span class="op">=</span> <span class="bn">0xd800</span>;</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">inline</span> <span class="kw">constexpr</span> <span class="dt">uint32_t</span> high_surrogate_max <span class="op">=</span> <span class="bn">0xdbff</span>;</span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">inline</span> <span class="kw">constexpr</span> <span class="dt">uint32_t</span> low_surrogate_min <span class="op">=</span> <span class="bn">0xdc00</span>;</span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">inline</span> <span class="kw">constexpr</span> <span class="dt">uint32_t</span> low_surrogate_max <span class="op">=</span> <span class="bn">0xdfff</span>;</span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">inline</span> <span class="kw">constexpr</span> <span class="dt">uint32_t</span> replacement_character <span class="op">=</span> <span class="bn">0xfffd</span>;</span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Returns is_high_surrogate(c) || is_low_surrogate(c).</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> is_surrogate<span class="op">(</span><span class="dt">uint32_t</span> c<span class="op">)</span>;</span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Returns true iff c is a Unicode high surrogate.</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> is_high_surrogate<span class="op">(</span><span class="dt">uint32_t</span> c<span class="op">)</span>;</span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Returns true iff c is a Unicode low surrogate.</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> is_low_surrogate<span class="op">(</span><span class="dt">uint32_t</span> c<span class="op">)</span>;</span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Returns true iff c is a Unicode reserved noncharacter.</span></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> is_reserved_noncharacter<span class="op">(</span><span class="dt">uint32_t</span> c<span class="op">)</span>;</span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Returns true iff c is a valid Unicode scalar value.</span></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> is_scalar_value<span class="op">(</span><span class="dt">uint32_t</span> c<span class="op">)</span>;</span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Returns true iff c is a Unicode scalar value not in the reserved</span></span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true" tabindex="-1"></a>  <span class="co">// range.</span></span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> is_unreserved_scalar_value<span class="op">(</span><span class="dt">uint32_t</span> c<span class="op">)</span>;</span>
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-29"><a href="#cb8-29" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Returns true iff c is a UTF-8 lead code unit (which must be followed</span></span>
<span id="cb8-30"><a href="#cb8-30" aria-hidden="true" tabindex="-1"></a>  <span class="co">// by 1-3 following units).</span></span>
<span id="cb8-31"><a href="#cb8-31" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> is_lead_code_unit<span class="op">(</span><span class="dt">unsigned</span> <span class="dt">char</span> c<span class="op">)</span>;</span>
<span id="cb8-32"><a href="#cb8-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-33"><a href="#cb8-33" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Returns true iff c is a UTF-8 continuation (non-lead) code unit.</span></span>
<span id="cb8-34"><a href="#cb8-34" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> is_continuation<span class="op">(</span><span class="dt">unsigned</span> <span class="dt">char</span> c<span class="op">)</span>;</span>
<span id="cb8-35"><a href="#cb8-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-36"><a href="#cb8-36" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Given the first (and possibly only) code unit of a UTF-8-encoded code</span></span>
<span id="cb8-37"><a href="#cb8-37" aria-hidden="true" tabindex="-1"></a>  <span class="co">// point, returns the number of bytes occupied by that code point (in the</span></span>
<span id="cb8-38"><a href="#cb8-38" aria-hidden="true" tabindex="-1"></a>  <span class="co">// range [1, 4]).  Returns a value &lt; 0 if first_unit is not a valid</span></span>
<span id="cb8-39"><a href="#cb8-39" aria-hidden="true" tabindex="-1"></a>  <span class="co">// initial UTF-8 code unit.</span></span>
<span id="cb8-40"><a href="#cb8-40" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">int</span> utf8_code_units<span class="op">(</span><span class="dt">unsigned</span> <span class="dt">char</span> first_unit<span class="op">)</span>;</span>
<span id="cb8-41"><a href="#cb8-41" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-42"><a href="#cb8-42" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Given the first (and possibly only) code unit of a UTF-16-encoded code</span></span>
<span id="cb8-43"><a href="#cb8-43" aria-hidden="true" tabindex="-1"></a>  <span class="co">// point, returns the number of code units occupied by that code point</span></span>
<span id="cb8-44"><a href="#cb8-44" aria-hidden="true" tabindex="-1"></a>  <span class="co">// (in the range [1, 2]).  Returns a value &lt; 0 if first_unit is</span></span>
<span id="cb8-45"><a href="#cb8-45" aria-hidden="true" tabindex="-1"></a>  <span class="co">// not a valid initial UTF-16 code unit.</span></span>
<span id="cb8-46"><a href="#cb8-46" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">int</span> utf16_code_units<span class="op">(</span><span class="dt">uint16_t</span> first_unit<span class="op">)</span>;</span>
<span id="cb8-47"><a href="#cb8-47" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-48"><a href="#cb8-48" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Returns the first code unit in [first, last) that is not properly</span></span>
<span id="cb8-49"><a href="#cb8-49" aria-hidden="true" tabindex="-1"></a>  <span class="co">// UTF-8 encoded, or last if no such code unit is found.</span></span>
<span id="cb8-50"><a href="#cb8-50" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>utf8_iter I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S <span class="op">=</span> I<span class="op">&gt;</span></span>
<span id="cb8-51"><a href="#cb8-51" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> random_access_iterator<span class="op">&lt;</span>I<span class="op">&gt;</span></span>
<span id="cb8-52"><a href="#cb8-52" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> I find_invalid_encoding<span class="op">(</span>I first, S last<span class="op">)</span>;</span>
<span id="cb8-53"><a href="#cb8-53" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-54"><a href="#cb8-54" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Returns the first code unit in [first, last) that is not properly</span></span>
<span id="cb8-55"><a href="#cb8-55" aria-hidden="true" tabindex="-1"></a>  <span class="co">// UTF-16 encoded, or last if no such code unit is found.</span></span>
<span id="cb8-56"><a href="#cb8-56" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>utf16_iter I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S <span class="op">=</span> I<span class="op">&gt;</span></span>
<span id="cb8-57"><a href="#cb8-57" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> random_access_iterator<span class="op">&lt;</span>I<span class="op">&gt;</span></span>
<span id="cb8-58"><a href="#cb8-58" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> I find_invalid_encoding<span class="op">(</span>I first, S last<span class="op">)</span>;</span>
<span id="cb8-59"><a href="#cb8-59" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-60"><a href="#cb8-60" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Returns true iff [first, last) is properly UTF-8 encoded.</span></span>
<span id="cb8-61"><a href="#cb8-61" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>utf8_iter I<span class="op">&gt;</span></span>
<span id="cb8-62"><a href="#cb8-62" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> random_access_iterator<span class="op">&lt;</span>I<span class="op">&gt;</span></span>
<span id="cb8-63"><a href="#cb8-63" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="dt">bool</span> is_encoded<span class="op">(</span>I first, I last<span class="op">)</span>;</span>
<span id="cb8-64"><a href="#cb8-64" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-65"><a href="#cb8-65" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Returns true iff [first, last) is properly UTF-16 encoded</span></span>
<span id="cb8-66"><a href="#cb8-66" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>utf16_iter I<span class="op">&gt;</span></span>
<span id="cb8-67"><a href="#cb8-67" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> random_access_iterator<span class="op">&lt;</span>I<span class="op">&gt;</span></span>
<span id="cb8-68"><a href="#cb8-68" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="dt">bool</span> is_encoded<span class="op">(</span>I first, I last<span class="op">)</span>;</span>
<span id="cb8-69"><a href="#cb8-69" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-70"><a href="#cb8-70" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Returns true iff [first, last) is empty or the initial UTF-8 code</span></span>
<span id="cb8-71"><a href="#cb8-71" aria-hidden="true" tabindex="-1"></a>  <span class="co">// units in [first, last) form a valid Unicode code point.</span></span>
<span id="cb8-72"><a href="#cb8-72" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>utf8_iter I<span class="op">&gt;</span></span>
<span id="cb8-73"><a href="#cb8-73" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> random_access_iterator<span class="op">&lt;</span>I<span class="op">&gt;</span></span>
<span id="cb8-74"><a href="#cb8-74" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="dt">bool</span> starts_encoded<span class="op">(</span>I first, I last<span class="op">)</span>;</span>
<span id="cb8-75"><a href="#cb8-75" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-76"><a href="#cb8-76" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Returns true iff [first, last) is empty or the initial UTF-16 code</span></span>
<span id="cb8-77"><a href="#cb8-77" aria-hidden="true" tabindex="-1"></a>  <span class="co">// units in [first, last) form a valid Unicode code point.</span></span>
<span id="cb8-78"><a href="#cb8-78" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>utf16_iter I<span class="op">&gt;</span></span>
<span id="cb8-79"><a href="#cb8-79" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> random_access_iterator<span class="op">&lt;</span>I<span class="op">&gt;</span></span>
<span id="cb8-80"><a href="#cb8-80" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="dt">bool</span> starts_encoded<span class="op">(</span>I first, I last<span class="op">)</span>;</span>
<span id="cb8-81"><a href="#cb8-81" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-82"><a href="#cb8-82" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Returns true iff [first, last) is empty or the final UTF-8 code</span></span>
<span id="cb8-83"><a href="#cb8-83" aria-hidden="true" tabindex="-1"></a>  <span class="co">// units in [first, last) form a valid Unicode code point.</span></span>
<span id="cb8-84"><a href="#cb8-84" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>utf8_iter I<span class="op">&gt;</span></span>
<span id="cb8-85"><a href="#cb8-85" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> random_access_iterator<span class="op">&lt;</span>I<span class="op">&gt;</span></span>
<span id="cb8-86"><a href="#cb8-86" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="dt">bool</span> ends_encoded<span class="op">(</span>I first, I last<span class="op">)</span>;</span>
<span id="cb8-87"><a href="#cb8-87" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-88"><a href="#cb8-88" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Returns true iff [first, last) is empty or the final UTF-16 code</span></span>
<span id="cb8-89"><a href="#cb8-89" aria-hidden="true" tabindex="-1"></a>  <span class="co">// units in [first, last) form a valid Unicode code point.</span></span>
<span id="cb8-90"><a href="#cb8-90" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>utf16_iter I<span class="op">&gt;</span></span>
<span id="cb8-91"><a href="#cb8-91" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> random_access_iterator<span class="op">&lt;</span>I<span class="op">&gt;</span></span>
<span id="cb8-92"><a href="#cb8-92" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="dt">bool</span> ends_encoded<span class="op">(</span>I first, I last<span class="op">)</span>;</span>
<span id="cb8-93"><a href="#cb8-93" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="4.5" id="add-transcode-algorithms"><span class="header-section-number">4.5</span> Add transcode algorithms<a href="#add-transcode-algorithms" class="self-link"></a></h2>
<p>These algorithms take an iterator/sentinel pair, a range, or a
null-terminated string, and transcode the input to the output
iterator.</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="kw">namespace</span> std<span class="op">::</span>uc <span class="op">{</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">// An alias for in_out_result returned by algorithms that perform a</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// transcoding copy.</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Iter, <span class="kw">class</span> OutIter<span class="op">&gt;</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> transcode_result <span class="op">=</span> in_out_result<span class="op">&lt;</span>Iter, OutIter<span class="op">&gt;</span>;</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>  </span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>range-like-result-iterator</em> <span class="op">=</span> <em>see below</em>; <span class="co">// <em>exposition only</em></span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// -&gt; UTF-8</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>input_iterator I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S, output_iterator<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;</span> O<span class="op">&gt;</span></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span>utf16_code_unit<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span> <span class="op">||</span> utf32_code_unit<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;)</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> transcode_result<span class="op">&lt;</span>I, O<span class="op">&gt;</span> transcode_to_utf8<span class="op">(</span>I first, S last, O out<span class="op">)</span>;</span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> R, output_iterator<span class="op">&lt;</span><span class="dt">uint32_t</span><span class="op">&gt;</span> O<span class="op">&gt;</span></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span>utf16_input_range_like<span class="op">&lt;</span>R<span class="op">&gt;</span> <span class="op">||</span> utf32_input_range_like<span class="op">&lt;</span>R<span class="op">&gt;)</span></span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> transcode_result<span class="op">&lt;</span><em>range-like-result-iterator</em><span class="op">&lt;</span>R<span class="op">&gt;</span>, O<span class="op">&gt;</span> transcode_to_utf8<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, O out<span class="op">)</span>;</span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true" tabindex="-1"></a>  <span class="co">// -&gt; UTF-16</span></span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-22"><a href="#cb9-22" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>input_iterator I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S, output_iterator<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;</span> O<span class="op">&gt;</span></span>
<span id="cb9-23"><a href="#cb9-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span>utf8_code_unit<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span> <span class="op">||</span> utf32_code_unit<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;)</span></span>
<span id="cb9-24"><a href="#cb9-24" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> transcode_result<span class="op">&lt;</span>I, O<span class="op">&gt;</span> transcode_to_utf16<span class="op">(</span>I first, S last, O out<span class="op">)</span>;</span>
<span id="cb9-25"><a href="#cb9-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-26"><a href="#cb9-26" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> R, output_iterator<span class="op">&lt;</span><span class="dt">uint32_t</span><span class="op">&gt;</span> O<span class="op">&gt;</span></span>
<span id="cb9-27"><a href="#cb9-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span>utf8_input_range_like<span class="op">&lt;</span>R<span class="op">&gt;</span> <span class="op">||</span> utf32_input_range_like<span class="op">&lt;</span>R<span class="op">&gt;)</span></span>
<span id="cb9-28"><a href="#cb9-28" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> transcode_result<span class="op">&lt;</span><em>range-like-result-iterator</em><span class="op">&lt;</span>R<span class="op">&gt;</span>, O<span class="op">&gt;</span> transcode_to_utf16<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, O out<span class="op">)</span>;</span>
<span id="cb9-29"><a href="#cb9-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-30"><a href="#cb9-30" aria-hidden="true" tabindex="-1"></a>  <span class="co">// -&gt; UTF-32</span></span>
<span id="cb9-31"><a href="#cb9-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-32"><a href="#cb9-32" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>input_iterator I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S, output_iterator<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;</span> O<span class="op">&gt;</span></span>
<span id="cb9-33"><a href="#cb9-33" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span>utf8_code_unit<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span> <span class="op">||</span> utf16_code_unit<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;)</span></span>
<span id="cb9-34"><a href="#cb9-34" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> transcode_result<span class="op">&lt;</span>I, O<span class="op">&gt;</span> transcode_to_utf32<span class="op">(</span>I first, S last, O out<span class="op">)</span>;</span>
<span id="cb9-35"><a href="#cb9-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-36"><a href="#cb9-36" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> R, output_iterator<span class="op">&lt;</span><span class="dt">uint32_t</span><span class="op">&gt;</span> O<span class="op">&gt;</span></span>
<span id="cb9-37"><a href="#cb9-37" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span>utf8_input_range_like<span class="op">&lt;</span>R<span class="op">&gt;</span> <span class="op">||</span> utf16_input_range_like<span class="op">&lt;</span>R<span class="op">&gt;)</span></span>
<span id="cb9-38"><a href="#cb9-38" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> transcode_result<span class="op">&lt;</span><em>range-like-result-iterator</em><span class="op">&lt;</span>R<span class="op">&gt;</span>, O<span class="op">&gt;</span> transcode_to_utf32<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, O out<span class="op">)</span>;</span>
<span id="cb9-39"><a href="#cb9-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-40"><a href="#cb9-40" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><code class="sourceCode default"><em>range-like-result-iterator</em>&lt;T&gt;</code>
is <code class="sourceCode default">T</code> if <code class="sourceCode default">is_pointer_v&lt;remove_reference_t&lt;T&gt;&gt;</code>
is <code class="sourceCode default">true</code>, and <code class="sourceCode default">ranges::borrowed_iterator_t&lt;T&gt;</code>
otherwise.</p>
<h2 data-number="4.6" id="add-the-transcoding-iterators"><span class="header-section-number">4.6</span> Add the transcoding iterators<a href="#add-the-transcoding-iterators" class="self-link"></a></h2>
<h3 data-number="4.6.1" id="first-the-basic-ones"><span class="header-section-number">4.6.1</span> First, the basic ones<a href="#first-the-basic-ones" class="self-link"></a></h3>
<p>I’m using <a href="https://isocpp.org/files/papers/P2727R0.html">P2727</a>’s
<code class="sourceCode default">iterator_interface</code> here for
simplicity.</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="kw">namespace</span> std<span class="op">::</span>uc <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">// An error handler type that can be used with the converting iterators;</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// provides the Unicode replacement character on errors.</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> use_replacement_character <span class="op">{</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">uint32_t</span> <span class="kw">operator</span><span class="op">()(</span><span class="kw">const</span> <span class="dt">char</span><span class="op">*)</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> replacement_character; <span class="op">}</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>    utf32_iter I,</span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>    sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S <span class="op">=</span> I,</span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>    transcoding_error_handler ErrorHandler <span class="op">=</span> use_replacement_character<span class="op">&gt;</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_32_to_8_iterator</span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> iterator_interface<span class="op">&lt;</span>utf_32_to_8_iterator<span class="op">&lt;</span>I, S, ErrorHandler<span class="op">&gt;</span>, bidirectional_iterator_tag, <span class="dt">char</span>, <span class="dt">char</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_8_iterator<span class="op">()</span>;</span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> utf_32_to_8_iterator<span class="op">(</span>I first, I it, S last<span class="op">)</span>;</span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I2, <span class="kw">class</span> S2<span class="op">&gt;</span></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> convertible_to<span class="op">&lt;</span>I2, I<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> convertible_to<span class="op">&lt;</span>S2, S<span class="op">&gt;</span></span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>        <span class="kw">constexpr</span> utf_32_to_8_iterator<span class="op">(</span></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a>          <span class="kw">const</span> utf_32_to_8_iterator<span class="op">&lt;</span>I2, S2, ErrorHandler<span class="op">&gt;&amp;</span> other<span class="op">)</span>;</span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> I begin<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> first_; <span class="op">}</span></span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> S end<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> last_; <span class="op">}</span></span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">char</span> <span class="kw">operator</span><span class="op">*()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> buf_<span class="op">[</span>index_<span class="op">]</span>; <span class="op">}</span></span>
<span id="cb10-25"><a href="#cb10-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-26"><a href="#cb10-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> I base<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> it_; <span class="op">}</span></span>
<span id="cb10-27"><a href="#cb10-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-28"><a href="#cb10-28" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_8_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">++()</span>;</span>
<span id="cb10-29"><a href="#cb10-29" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_8_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">--()</span>;</span>
<span id="cb10-30"><a href="#cb10-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-31"><a href="#cb10-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-32"><a href="#cb10-32" aria-hidden="true" tabindex="-1"></a>      <span class="kw">class</span> I1, <span class="kw">class</span> S1,</span>
<span id="cb10-33"><a href="#cb10-33" aria-hidden="true" tabindex="-1"></a>      <span class="kw">class</span> I2, <span class="kw">class</span> S2,</span>
<span id="cb10-34"><a href="#cb10-34" aria-hidden="true" tabindex="-1"></a>      <span class="kw">class</span> ErrorHandler2<span class="op">&gt;</span></span>
<span id="cb10-35"><a href="#cb10-35" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span></span>
<span id="cb10-36"><a href="#cb10-36" aria-hidden="true" tabindex="-1"></a>      <span class="kw">const</span> utf_32_to_8_iterator<span class="op">&lt;</span>I1, S1, ErrorHandler2<span class="op">&gt;&amp;</span> lhs,</span>
<span id="cb10-37"><a href="#cb10-37" aria-hidden="true" tabindex="-1"></a>      <span class="kw">const</span> utf_32_to_8_iterator<span class="op">&lt;</span>I2, S2, ErrorHandler2<span class="op">&gt;&amp;</span> rhs<span class="op">)</span></span>
<span id="cb10-38"><a href="#cb10-38" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>base<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb10-39"><a href="#cb10-39" aria-hidden="true" tabindex="-1"></a>          <span class="op">{</span> <span class="cf">return</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>base<span class="op">()</span> <span class="op">&amp;&amp;</span> lhs<span class="op">.</span>index_ <span class="op">==</span> rhs<span class="op">.</span>index_; <span class="op">}</span></span>
<span id="cb10-40"><a href="#cb10-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-41"><a href="#cb10-41" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>utf_32_to_8_iterator lhs, utf_32_to_8_iterator rhs<span class="op">)</span></span>
<span id="cb10-42"><a href="#cb10-42" aria-hidden="true" tabindex="-1"></a>      <span class="op">{</span> <span class="cf">return</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>base<span class="op">()</span> <span class="op">&amp;&amp;</span> lhs<span class="op">.</span>index_ <span class="op">==</span> rhs<span class="op">.</span>index_; <span class="op">}</span></span>
<span id="cb10-43"><a href="#cb10-43" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-44"><a href="#cb10-44" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>base-type</em> <span class="op">=</span>         <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-45"><a href="#cb10-45" aria-hidden="true" tabindex="-1"></a>      iterator_interface<span class="op">&lt;</span>utf_32_to_8_iterator<span class="op">&lt;</span>I, S, ErrorHandler<span class="op">&gt;</span>,</span>
<span id="cb10-46"><a href="#cb10-46" aria-hidden="true" tabindex="-1"></a>                         bidirectional_iterator_tag,</span>
<span id="cb10-47"><a href="#cb10-47" aria-hidden="true" tabindex="-1"></a>                         <span class="dt">uint32_t</span>,</span>
<span id="cb10-48"><a href="#cb10-48" aria-hidden="true" tabindex="-1"></a>                         <span class="dt">uint32_t</span><span class="op">&gt;</span>;</span>
<span id="cb10-49"><a href="#cb10-49" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>base-type</em><span class="op">::</span><span class="kw">operator</span><span class="op">++</span>;</span>
<span id="cb10-50"><a href="#cb10-50" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>base-type</em><span class="op">::</span><span class="kw">operator</span><span class="op">--</span>;</span>
<span id="cb10-51"><a href="#cb10-51" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-52"><a href="#cb10-52" aria-hidden="true" tabindex="-1"></a>  <span class="kw">private</span><span class="op">:</span></span>
<span id="cb10-53"><a href="#cb10-53" aria-hidden="true" tabindex="-1"></a>    I first_;                 <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-54"><a href="#cb10-54" aria-hidden="true" tabindex="-1"></a>    I it_;                    <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-55"><a href="#cb10-55" aria-hidden="true" tabindex="-1"></a>    S last_;                  <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-56"><a href="#cb10-56" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> index_;               <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-57"><a href="#cb10-57" aria-hidden="true" tabindex="-1"></a>    array<span class="op">&lt;</span><span class="dt">char</span>, <span class="dv">5</span><span class="op">&gt;</span> buf_;      <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-58"><a href="#cb10-58" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-59"><a href="#cb10-59" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-60"><a href="#cb10-60" aria-hidden="true" tabindex="-1"></a>      utf32_iter I2,</span>
<span id="cb10-61"><a href="#cb10-61" aria-hidden="true" tabindex="-1"></a>      sentinel_for<span class="op">&lt;</span>I2<span class="op">&gt;</span> S2,</span>
<span id="cb10-62"><a href="#cb10-62" aria-hidden="true" tabindex="-1"></a>      transcoding_error_handler ErrorHandler2<span class="op">&gt;</span></span>
<span id="cb10-63"><a href="#cb10-63" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">struct</span> utf_32_to_8_iterator;</span>
<span id="cb10-64"><a href="#cb10-64" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb10-65"><a href="#cb10-65" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-66"><a href="#cb10-66" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I, <span class="kw">class</span> S, <span class="kw">class</span> ErrorHandler<span class="op">&gt;</span></span>
<span id="cb10-67"><a href="#cb10-67" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span></span>
<span id="cb10-68"><a href="#cb10-68" aria-hidden="true" tabindex="-1"></a>      utf_32_to_8_iterator<span class="op">&lt;</span>I, S, ErrorHandler<span class="op">&gt;</span> lhs, S rhs<span class="op">)</span></span>
<span id="cb10-69"><a href="#cb10-69" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs; <span class="op">}</span>;</span>
<span id="cb10-70"><a href="#cb10-70" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-71"><a href="#cb10-71" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-72"><a href="#cb10-72" aria-hidden="true" tabindex="-1"></a>    utf8_iter I,</span>
<span id="cb10-73"><a href="#cb10-73" aria-hidden="true" tabindex="-1"></a>    sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S <span class="op">=</span> I,</span>
<span id="cb10-74"><a href="#cb10-74" aria-hidden="true" tabindex="-1"></a>    transcoding_error_handler ErrorHandler <span class="op">=</span> use_replacement_character<span class="op">&gt;</span></span>
<span id="cb10-75"><a href="#cb10-75" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_8_to_32_iterator</span>
<span id="cb10-76"><a href="#cb10-76" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> iterator_interface<span class="op">&lt;</span>utf_8_to_32_iterator<span class="op">&lt;</span>I, S, ErrorHandler<span class="op">&gt;</span>, bidirectional_iterator_tag, <span class="dt">uint32_t</span>, <span class="dt">uint32_t</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb10-77"><a href="#cb10-77" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_32_iterator<span class="op">()</span>;</span>
<span id="cb10-78"><a href="#cb10-78" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> utf_8_to_32_iterator<span class="op">(</span>I first, I it, S last<span class="op">)</span>;</span>
<span id="cb10-79"><a href="#cb10-79" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I2, <span class="kw">class</span> S2<span class="op">&gt;</span></span>
<span id="cb10-80"><a href="#cb10-80" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> convertible_to<span class="op">&lt;</span>I2, I<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> convertible_to<span class="op">&lt;</span>S2, S<span class="op">&gt;</span></span>
<span id="cb10-81"><a href="#cb10-81" aria-hidden="true" tabindex="-1"></a>        <span class="kw">constexpr</span> utf_8_to_32_iterator<span class="op">(</span></span>
<span id="cb10-82"><a href="#cb10-82" aria-hidden="true" tabindex="-1"></a>          <span class="kw">const</span> utf_8_to_32_iterator<span class="op">&lt;</span>I2, S2, ErrorHandler<span class="op">&gt;&amp;</span> other<span class="op">)</span>;</span>
<span id="cb10-83"><a href="#cb10-83" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-84"><a href="#cb10-84" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> I begin<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> first_; <span class="op">}</span></span>
<span id="cb10-85"><a href="#cb10-85" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> S end<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> last_; <span class="op">}</span></span>
<span id="cb10-86"><a href="#cb10-86" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-87"><a href="#cb10-87" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">uint32_t</span> <span class="kw">operator</span><span class="op">*()</span> <span class="kw">const</span>;</span>
<span id="cb10-88"><a href="#cb10-88" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-89"><a href="#cb10-89" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> I base<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> it_; <span class="op">}</span></span>
<span id="cb10-90"><a href="#cb10-90" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-91"><a href="#cb10-91" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_32_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">++()</span>;</span>
<span id="cb10-92"><a href="#cb10-92" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_32_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">--()</span>;</span>
<span id="cb10-93"><a href="#cb10-93" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-94"><a href="#cb10-94" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>utf_8_to_32_iterator lhs, utf_8_to_32_iterator rhs<span class="op">)</span></span>
<span id="cb10-95"><a href="#cb10-95" aria-hidden="true" tabindex="-1"></a>      <span class="op">{</span> <span class="cf">return</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>base<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb10-96"><a href="#cb10-96" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-97"><a href="#cb10-97" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>base-type</em> <span class="op">=</span>         <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-98"><a href="#cb10-98" aria-hidden="true" tabindex="-1"></a>      iterator_interface<span class="op">&lt;</span>utf_8_to_32_iterator<span class="op">&lt;</span>I, S, ErrorHandler<span class="op">&gt;</span>,</span>
<span id="cb10-99"><a href="#cb10-99" aria-hidden="true" tabindex="-1"></a>                         bidirectional_iterator_tag,</span>
<span id="cb10-100"><a href="#cb10-100" aria-hidden="true" tabindex="-1"></a>                         <span class="dt">uint32_t</span>,</span>
<span id="cb10-101"><a href="#cb10-101" aria-hidden="true" tabindex="-1"></a>                         <span class="dt">uint32_t</span><span class="op">&gt;</span>;</span>
<span id="cb10-102"><a href="#cb10-102" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>base-type</em><span class="op">::</span><span class="kw">operator</span><span class="op">++</span>;</span>
<span id="cb10-103"><a href="#cb10-103" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>base-type</em><span class="op">::</span><span class="kw">operator</span><span class="op">--</span>;</span>
<span id="cb10-104"><a href="#cb10-104" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-105"><a href="#cb10-105" aria-hidden="true" tabindex="-1"></a>  <span class="kw">private</span><span class="op">:</span></span>
<span id="cb10-106"><a href="#cb10-106" aria-hidden="true" tabindex="-1"></a>    I first_;                 <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-107"><a href="#cb10-107" aria-hidden="true" tabindex="-1"></a>    I it_;                    <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-108"><a href="#cb10-108" aria-hidden="true" tabindex="-1"></a>    S last_;                  <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-109"><a href="#cb10-109" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-110"><a href="#cb10-110" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-111"><a href="#cb10-111" aria-hidden="true" tabindex="-1"></a>      utf8_iter I2,</span>
<span id="cb10-112"><a href="#cb10-112" aria-hidden="true" tabindex="-1"></a>      sentinel_for<span class="op">&lt;</span>I2<span class="op">&gt;</span> S2,</span>
<span id="cb10-113"><a href="#cb10-113" aria-hidden="true" tabindex="-1"></a>      transcoding_error_handler ErrorHandler2<span class="op">&gt;</span></span>
<span id="cb10-114"><a href="#cb10-114" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">struct</span> utf_8_to_16_iterator;</span>
<span id="cb10-115"><a href="#cb10-115" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-116"><a href="#cb10-116" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-117"><a href="#cb10-117" aria-hidden="true" tabindex="-1"></a>      utf8_iter I2,</span>
<span id="cb10-118"><a href="#cb10-118" aria-hidden="true" tabindex="-1"></a>      sentinel_for<span class="op">&lt;</span>I2<span class="op">&gt;</span> S2,</span>
<span id="cb10-119"><a href="#cb10-119" aria-hidden="true" tabindex="-1"></a>      transcoding_error_handler ErrorHandler2<span class="op">&gt;</span></span>
<span id="cb10-120"><a href="#cb10-120" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">struct</span> utf_8_to_32_iterator;</span>
<span id="cb10-121"><a href="#cb10-121" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb10-122"><a href="#cb10-122" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-123"><a href="#cb10-123" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I, <span class="kw">class</span> S, <span class="kw">class</span> ErrorHandler<span class="op">&gt;</span></span>
<span id="cb10-124"><a href="#cb10-124" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span></span>
<span id="cb10-125"><a href="#cb10-125" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> utf_8_to_32_iterator<span class="op">&lt;</span>I, S, ErrorHandler<span class="op">&gt;&amp;</span> lhs, Sentinel rhs<span class="op">)</span></span>
<span id="cb10-126"><a href="#cb10-126" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs; <span class="op">}</span>;</span>
<span id="cb10-127"><a href="#cb10-127" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-128"><a href="#cb10-128" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-129"><a href="#cb10-129" aria-hidden="true" tabindex="-1"></a>    <span class="kw">class</span> I1, <span class="kw">class</span> S1,</span>
<span id="cb10-130"><a href="#cb10-130" aria-hidden="true" tabindex="-1"></a>    <span class="kw">class</span> I2, <span class="kw">class</span> S2,</span>
<span id="cb10-131"><a href="#cb10-131" aria-hidden="true" tabindex="-1"></a>    <span class="kw">class</span> ErrorHandler<span class="op">&gt;</span></span>
<span id="cb10-132"><a href="#cb10-132" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span></span>
<span id="cb10-133"><a href="#cb10-133" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> utf_8_to_32_iterator<span class="op">&lt;</span>I1, S1, ErrorHandler<span class="op">&gt;&amp;</span> lhs,</span>
<span id="cb10-134"><a href="#cb10-134" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> utf_8_to_32_iterator<span class="op">&lt;</span>I2, S2, ErrorHandler<span class="op">&gt;&amp;</span> rhs<span class="op">)</span></span>
<span id="cb10-135"><a href="#cb10-135" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>base<span class="op">()</span>; <span class="op">}</span>;</span>
<span id="cb10-136"><a href="#cb10-136" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-137"><a href="#cb10-137" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-138"><a href="#cb10-138" aria-hidden="true" tabindex="-1"></a>    utf32_iter I,</span>
<span id="cb10-139"><a href="#cb10-139" aria-hidden="true" tabindex="-1"></a>    sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S <span class="op">=</span> I,</span>
<span id="cb10-140"><a href="#cb10-140" aria-hidden="true" tabindex="-1"></a>    transcoding_error_handler ErrorHandler <span class="op">=</span> use_replacement_character<span class="op">&gt;</span></span>
<span id="cb10-141"><a href="#cb10-141" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_32_to_16_iterator</span>
<span id="cb10-142"><a href="#cb10-142" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> iterator_interface<span class="op">&lt;</span>utf_32_to_16_iterator<span class="op">&lt;</span>I, S, ErrorHandler<span class="op">&gt;</span>, bidirectional_iterator_tag, <span class="dt">uint16_t</span>, <span class="dt">uint16_t</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb10-143"><a href="#cb10-143" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_16_iterator<span class="op">()</span>;</span>
<span id="cb10-144"><a href="#cb10-144" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> utf_32_to_16_iterator<span class="op">(</span>I first, I it, S last<span class="op">)</span>;</span>
<span id="cb10-145"><a href="#cb10-145" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I2, <span class="kw">class</span> S2<span class="op">&gt;</span></span>
<span id="cb10-146"><a href="#cb10-146" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> convertible_to<span class="op">&lt;</span>I2, I<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> convertible_to<span class="op">&lt;</span>S2, S<span class="op">&gt;</span></span>
<span id="cb10-147"><a href="#cb10-147" aria-hidden="true" tabindex="-1"></a>        <span class="kw">constexpr</span> utf_32_to_16_iterator<span class="op">(</span></span>
<span id="cb10-148"><a href="#cb10-148" aria-hidden="true" tabindex="-1"></a>          <span class="kw">const</span> utf_32_to_16_iterator<span class="op">&lt;</span>I2, S2, ErrorHandler<span class="op">&gt;&amp;</span> other<span class="op">)</span>;</span>
<span id="cb10-149"><a href="#cb10-149" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-150"><a href="#cb10-150" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> I begin<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> first_; <span class="op">}</span></span>
<span id="cb10-151"><a href="#cb10-151" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> S end<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> last_; <span class="op">}</span></span>
<span id="cb10-152"><a href="#cb10-152" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-153"><a href="#cb10-153" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">uint16_t</span> <span class="kw">operator</span><span class="op">*()</span> <span class="kw">const</span></span>
<span id="cb10-154"><a href="#cb10-154" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span> <span class="cf">return</span> buf_<span class="op">[</span>index_<span class="op">]</span>; <span class="op">}</span></span>
<span id="cb10-155"><a href="#cb10-155" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-156"><a href="#cb10-156" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> I base<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> it_; <span class="op">}</span></span>
<span id="cb10-157"><a href="#cb10-157" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-158"><a href="#cb10-158" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_16_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">++()</span>;</span>
<span id="cb10-159"><a href="#cb10-159" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_16_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">--()</span>;</span>
<span id="cb10-160"><a href="#cb10-160" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-161"><a href="#cb10-161" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-162"><a href="#cb10-162" aria-hidden="true" tabindex="-1"></a>      <span class="kw">class</span> I1, <span class="kw">class</span> S1,</span>
<span id="cb10-163"><a href="#cb10-163" aria-hidden="true" tabindex="-1"></a>      <span class="kw">class</span> I2, <span class="kw">class</span> S2,</span>
<span id="cb10-164"><a href="#cb10-164" aria-hidden="true" tabindex="-1"></a>      <span class="kw">class</span> ErrorHandler2<span class="op">&gt;</span></span>
<span id="cb10-165"><a href="#cb10-165" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span></span>
<span id="cb10-166"><a href="#cb10-166" aria-hidden="true" tabindex="-1"></a>      <span class="kw">const</span> utf_32_to_16_iterator<span class="op">&lt;</span>I1, S1, ErrorHandler2<span class="op">&gt;&amp;</span> lhs,</span>
<span id="cb10-167"><a href="#cb10-167" aria-hidden="true" tabindex="-1"></a>      <span class="kw">const</span> utf_32_to_16_iterator<span class="op">&lt;</span>I2, S2, ErrorHandler2<span class="op">&gt;&amp;</span> rhs<span class="op">)</span></span>
<span id="cb10-168"><a href="#cb10-168" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>base<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb10-169"><a href="#cb10-169" aria-hidden="true" tabindex="-1"></a>          <span class="op">{</span> <span class="cf">return</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>base<span class="op">()</span> <span class="op">&amp;&amp;</span> lhs<span class="op">.</span>index_ <span class="op">==</span> rhs<span class="op">.</span>index_; <span class="op">}</span></span>
<span id="cb10-170"><a href="#cb10-170" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-171"><a href="#cb10-171" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>utf_32_to_16_iterator lhs, utf_32_to_16_iterator rhs<span class="op">)</span></span>
<span id="cb10-172"><a href="#cb10-172" aria-hidden="true" tabindex="-1"></a>      <span class="op">{</span> <span class="cf">return</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>base<span class="op">()</span> <span class="op">&amp;&amp;</span> lhs<span class="op">.</span>index_ <span class="op">==</span> rhs<span class="op">.</span>index_; <span class="op">}</span></span>
<span id="cb10-173"><a href="#cb10-173" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-174"><a href="#cb10-174" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>base-type</em> <span class="op">=</span>         <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-175"><a href="#cb10-175" aria-hidden="true" tabindex="-1"></a>      iterator_interface<span class="op">&lt;</span>utf_32_to_16_iterator<span class="op">&lt;</span>I, S, ErrorHandler<span class="op">&gt;</span>,</span>
<span id="cb10-176"><a href="#cb10-176" aria-hidden="true" tabindex="-1"></a>                         bidirectional_iterator_tag,</span>
<span id="cb10-177"><a href="#cb10-177" aria-hidden="true" tabindex="-1"></a>                         <span class="dt">uint16_t</span>,</span>
<span id="cb10-178"><a href="#cb10-178" aria-hidden="true" tabindex="-1"></a>                         <span class="dt">uint16_t</span><span class="op">&gt;</span>;</span>
<span id="cb10-179"><a href="#cb10-179" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>base-type</em><span class="op">::</span><span class="kw">operator</span><span class="op">++</span>;</span>
<span id="cb10-180"><a href="#cb10-180" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>base-type</em><span class="op">::</span><span class="kw">operator</span><span class="op">--</span>;</span>
<span id="cb10-181"><a href="#cb10-181" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-182"><a href="#cb10-182" aria-hidden="true" tabindex="-1"></a>  <span class="kw">private</span><span class="op">:</span></span>
<span id="cb10-183"><a href="#cb10-183" aria-hidden="true" tabindex="-1"></a>    I first_;                 <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-184"><a href="#cb10-184" aria-hidden="true" tabindex="-1"></a>    I it_;                    <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-185"><a href="#cb10-185" aria-hidden="true" tabindex="-1"></a>    S last_;                  <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-186"><a href="#cb10-186" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> index_;               <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-187"><a href="#cb10-187" aria-hidden="true" tabindex="-1"></a>    array<span class="op">&lt;</span><span class="dt">uint16_t</span>, <span class="dv">4</span><span class="op">&gt;</span> buf_;  <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-188"><a href="#cb10-188" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-189"><a href="#cb10-189" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-190"><a href="#cb10-190" aria-hidden="true" tabindex="-1"></a>      utf32_iter I2,</span>
<span id="cb10-191"><a href="#cb10-191" aria-hidden="true" tabindex="-1"></a>      sentinel_for<span class="op">&lt;</span>I2<span class="op">&gt;</span> S2,</span>
<span id="cb10-192"><a href="#cb10-192" aria-hidden="true" tabindex="-1"></a>      transcoding_error_handler ErrorHandler2<span class="op">&gt;</span></span>
<span id="cb10-193"><a href="#cb10-193" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">struct</span> utf_32_to_16_iterator;</span>
<span id="cb10-194"><a href="#cb10-194" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb10-195"><a href="#cb10-195" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-196"><a href="#cb10-196" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I, <span class="kw">class</span> S, <span class="kw">class</span> ErrorHandler<span class="op">&gt;</span></span>
<span id="cb10-197"><a href="#cb10-197" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span></span>
<span id="cb10-198"><a href="#cb10-198" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> utf_32_to_16_iterator<span class="op">&lt;</span>I, S, ErrorHandler<span class="op">&gt;&amp;</span> lhs, Sentinel rhs<span class="op">)</span></span>
<span id="cb10-199"><a href="#cb10-199" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs; <span class="op">}</span>;</span>
<span id="cb10-200"><a href="#cb10-200" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-201"><a href="#cb10-201" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-202"><a href="#cb10-202" aria-hidden="true" tabindex="-1"></a>    utf16_iter I,</span>
<span id="cb10-203"><a href="#cb10-203" aria-hidden="true" tabindex="-1"></a>    sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S <span class="op">=</span> I,</span>
<span id="cb10-204"><a href="#cb10-204" aria-hidden="true" tabindex="-1"></a>    transcoding_error_handler ErrorHandler <span class="op">=</span> use_replacement_character<span class="op">&gt;</span></span>
<span id="cb10-205"><a href="#cb10-205" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_16_to_32_iterator</span>
<span id="cb10-206"><a href="#cb10-206" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> iterator_interface<span class="op">&lt;</span>utf_16_to_32_iterator<span class="op">&lt;</span>I, S, ErrorHandler<span class="op">&gt;</span>, bidirectional_iterator_tag, <span class="dt">uint32_t</span>, <span class="dt">uint32_t</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb10-207"><a href="#cb10-207" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_32_iterator<span class="op">()</span>;</span>
<span id="cb10-208"><a href="#cb10-208" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> utf_16_to_32_iterator<span class="op">(</span>I first, I it, S last<span class="op">)</span>;</span>
<span id="cb10-209"><a href="#cb10-209" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I2, <span class="kw">class</span> S2<span class="op">&gt;</span></span>
<span id="cb10-210"><a href="#cb10-210" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> convertible_to<span class="op">&lt;</span>I2, I<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> convertible_to<span class="op">&lt;</span>S2, S<span class="op">&gt;</span></span>
<span id="cb10-211"><a href="#cb10-211" aria-hidden="true" tabindex="-1"></a>        <span class="kw">constexpr</span> utf_16_to_32_iterator<span class="op">(</span></span>
<span id="cb10-212"><a href="#cb10-212" aria-hidden="true" tabindex="-1"></a>          <span class="kw">const</span> utf_16_to_32_iterator<span class="op">&lt;</span>I2, S2, ErrorHandler<span class="op">&gt;&amp;</span> other<span class="op">)</span>;</span>
<span id="cb10-213"><a href="#cb10-213" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-214"><a href="#cb10-214" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> I begin<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> first_; <span class="op">}</span></span>
<span id="cb10-215"><a href="#cb10-215" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> S end<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> last_; <span class="op">}</span></span>
<span id="cb10-216"><a href="#cb10-216" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-217"><a href="#cb10-217" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">uint32_t</span> <span class="kw">operator</span><span class="op">*()</span> <span class="kw">const</span>;</span>
<span id="cb10-218"><a href="#cb10-218" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-219"><a href="#cb10-219" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> I base<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> it_; <span class="op">}</span></span>
<span id="cb10-220"><a href="#cb10-220" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-221"><a href="#cb10-221" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_32_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">++()</span>;</span>
<span id="cb10-222"><a href="#cb10-222" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_32_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">--()</span>;</span>
<span id="cb10-223"><a href="#cb10-223" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-224"><a href="#cb10-224" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>utf_16_to_32_iterator lhs, utf_16_to_32_iterator rhs<span class="op">)</span></span>
<span id="cb10-225"><a href="#cb10-225" aria-hidden="true" tabindex="-1"></a>      <span class="op">{</span> <span class="cf">return</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>base<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb10-226"><a href="#cb10-226" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-227"><a href="#cb10-227" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>base-type</em> <span class="op">=</span>         <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-228"><a href="#cb10-228" aria-hidden="true" tabindex="-1"></a>      iterator_interface<span class="op">&lt;</span>utf_16_to_32_iterator<span class="op">&lt;</span>I, S, ErrorHandler<span class="op">&gt;</span>,</span>
<span id="cb10-229"><a href="#cb10-229" aria-hidden="true" tabindex="-1"></a>                         bidirectional_iterator_tag,</span>
<span id="cb10-230"><a href="#cb10-230" aria-hidden="true" tabindex="-1"></a>                         <span class="dt">uint32_t</span>,</span>
<span id="cb10-231"><a href="#cb10-231" aria-hidden="true" tabindex="-1"></a>                         <span class="dt">uint32_t</span><span class="op">&gt;</span>;</span>
<span id="cb10-232"><a href="#cb10-232" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>base-type</em><span class="op">::</span><span class="kw">operator</span><span class="op">++</span>;</span>
<span id="cb10-233"><a href="#cb10-233" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>base-type</em><span class="op">::</span><span class="kw">operator</span><span class="op">--</span>;</span>
<span id="cb10-234"><a href="#cb10-234" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-235"><a href="#cb10-235" aria-hidden="true" tabindex="-1"></a>  <span class="kw">private</span><span class="op">:</span></span>
<span id="cb10-236"><a href="#cb10-236" aria-hidden="true" tabindex="-1"></a>    I first_;                 <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-237"><a href="#cb10-237" aria-hidden="true" tabindex="-1"></a>    I it_;                    <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-238"><a href="#cb10-238" aria-hidden="true" tabindex="-1"></a>    S last_;                  <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-239"><a href="#cb10-239" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-240"><a href="#cb10-240" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-241"><a href="#cb10-241" aria-hidden="true" tabindex="-1"></a>      utf32_iter I2,</span>
<span id="cb10-242"><a href="#cb10-242" aria-hidden="true" tabindex="-1"></a>      sentinel_for<span class="op">&lt;</span>I2<span class="op">&gt;</span> S2,</span>
<span id="cb10-243"><a href="#cb10-243" aria-hidden="true" tabindex="-1"></a>      transcoding_error_handler ErrorHandler2<span class="op">&gt;</span></span>
<span id="cb10-244"><a href="#cb10-244" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">struct</span> utf_32_to_16_iterator;</span>
<span id="cb10-245"><a href="#cb10-245" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-246"><a href="#cb10-246" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-247"><a href="#cb10-247" aria-hidden="true" tabindex="-1"></a>      utf16_iter I2,</span>
<span id="cb10-248"><a href="#cb10-248" aria-hidden="true" tabindex="-1"></a>      sentinel_for<span class="op">&lt;</span>I2<span class="op">&gt;</span> S2,</span>
<span id="cb10-249"><a href="#cb10-249" aria-hidden="true" tabindex="-1"></a>      transcoding_error_handler ErrorHandler2<span class="op">&gt;</span></span>
<span id="cb10-250"><a href="#cb10-250" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">struct</span> utf_16_to_32_iterator;</span>
<span id="cb10-251"><a href="#cb10-251" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb10-252"><a href="#cb10-252" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-253"><a href="#cb10-253" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I, <span class="kw">class</span> S, <span class="kw">class</span> ErrorHandler<span class="op">&gt;</span></span>
<span id="cb10-254"><a href="#cb10-254" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span></span>
<span id="cb10-255"><a href="#cb10-255" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> utf_16_to_32_iterator<span class="op">&lt;</span>I, S, ErrorHandler<span class="op">&gt;&amp;</span> lhs, Sentinel rhs<span class="op">)</span></span>
<span id="cb10-256"><a href="#cb10-256" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs; <span class="op">}</span>;</span>
<span id="cb10-257"><a href="#cb10-257" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-258"><a href="#cb10-258" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-259"><a href="#cb10-259" aria-hidden="true" tabindex="-1"></a>    <span class="kw">class</span> I1, <span class="kw">class</span> S1,</span>
<span id="cb10-260"><a href="#cb10-260" aria-hidden="true" tabindex="-1"></a>    <span class="kw">class</span> I2, <span class="kw">class</span> S2,</span>
<span id="cb10-261"><a href="#cb10-261" aria-hidden="true" tabindex="-1"></a>    <span class="kw">class</span> ErrorHandler<span class="op">&gt;</span></span>
<span id="cb10-262"><a href="#cb10-262" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span></span>
<span id="cb10-263"><a href="#cb10-263" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> utf_16_to_32_iterator<span class="op">&lt;</span>I1, S1, ErrorHandler<span class="op">&gt;&amp;</span> lhs,</span>
<span id="cb10-264"><a href="#cb10-264" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> utf_16_to_32_iterator<span class="op">&lt;</span>I2, S2, ErrorHandler<span class="op">&gt;&amp;</span> rhs<span class="op">)</span></span>
<span id="cb10-265"><a href="#cb10-265" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>base<span class="op">()</span>; <span class="op">}</span>;</span>
<span id="cb10-266"><a href="#cb10-266" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-267"><a href="#cb10-267" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-268"><a href="#cb10-268" aria-hidden="true" tabindex="-1"></a>      utf16_iter I,</span>
<span id="cb10-269"><a href="#cb10-269" aria-hidden="true" tabindex="-1"></a>      sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S <span class="op">=</span> I,</span>
<span id="cb10-270"><a href="#cb10-270" aria-hidden="true" tabindex="-1"></a>      transcoding_error_handler ErrorHandler <span class="op">=</span> use_replacement_character<span class="op">&gt;</span></span>
<span id="cb10-271"><a href="#cb10-271" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_16_to_8_iterator</span>
<span id="cb10-272"><a href="#cb10-272" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> iterator_interface<span class="op">&lt;</span>utf_16_to_8_iterator<span class="op">&lt;</span>I, S, ErrorHandler<span class="op">&gt;</span>, bidirectional_iterator_tag, <span class="dt">char</span>, <span class="dt">char</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb10-273"><a href="#cb10-273" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_8_iterator<span class="op">()</span>;</span>
<span id="cb10-274"><a href="#cb10-274" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> utf_16_to_8_iterator<span class="op">(</span>I first, I it, S last<span class="op">)</span>;</span>
<span id="cb10-275"><a href="#cb10-275" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I2, <span class="kw">class</span> S2<span class="op">&gt;</span></span>
<span id="cb10-276"><a href="#cb10-276" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> convertible_to<span class="op">&lt;</span>I2, I<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> convertible_to<span class="op">&lt;</span>S2, S<span class="op">&gt;</span></span>
<span id="cb10-277"><a href="#cb10-277" aria-hidden="true" tabindex="-1"></a>        <span class="kw">constexpr</span> utf_16_to_8_iterator<span class="op">(</span><span class="kw">const</span> utf_16_to_8_iterator<span class="op">&lt;</span>I2, S2<span class="op">&gt;&amp;</span> other<span class="op">)</span>;</span>
<span id="cb10-278"><a href="#cb10-278" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-279"><a href="#cb10-279" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> I begin<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> first_; <span class="op">}</span></span>
<span id="cb10-280"><a href="#cb10-280" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> S end<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> last_; <span class="op">}</span></span>
<span id="cb10-281"><a href="#cb10-281" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-282"><a href="#cb10-282" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">char</span> <span class="kw">operator</span><span class="op">*()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> buf_<span class="op">[</span>index_<span class="op">]</span>; <span class="op">}</span></span>
<span id="cb10-283"><a href="#cb10-283" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-284"><a href="#cb10-284" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> I base<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> it_; <span class="op">}</span></span>
<span id="cb10-285"><a href="#cb10-285" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-286"><a href="#cb10-286" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_8_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">++()</span>;</span>
<span id="cb10-287"><a href="#cb10-287" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_8_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">--()</span>;</span>
<span id="cb10-288"><a href="#cb10-288" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-289"><a href="#cb10-289" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-290"><a href="#cb10-290" aria-hidden="true" tabindex="-1"></a>      <span class="kw">class</span> I1, <span class="kw">class</span> S1,</span>
<span id="cb10-291"><a href="#cb10-291" aria-hidden="true" tabindex="-1"></a>      <span class="kw">class</span> I2, <span class="kw">class</span> S2,</span>
<span id="cb10-292"><a href="#cb10-292" aria-hidden="true" tabindex="-1"></a>      <span class="kw">class</span> ErrorHandler2<span class="op">&gt;</span></span>
<span id="cb10-293"><a href="#cb10-293" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span></span>
<span id="cb10-294"><a href="#cb10-294" aria-hidden="true" tabindex="-1"></a>      <span class="kw">const</span> utf_16_to_8_iterator<span class="op">&lt;</span>I1, S1, ErrorHandler2<span class="op">&gt;&amp;</span> lhs,</span>
<span id="cb10-295"><a href="#cb10-295" aria-hidden="true" tabindex="-1"></a>      <span class="kw">const</span> utf_16_to_8_iterator<span class="op">&lt;</span>I2, S2, ErrorHandler2<span class="op">&gt;&amp;</span> rhs<span class="op">)</span></span>
<span id="cb10-296"><a href="#cb10-296" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>base<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb10-297"><a href="#cb10-297" aria-hidden="true" tabindex="-1"></a>          <span class="op">{</span> <span class="cf">return</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>base<span class="op">()</span> <span class="op">&amp;&amp;</span> lhs<span class="op">.</span>index_ <span class="op">==</span> rhs<span class="op">.</span>index_; <span class="op">}</span></span>
<span id="cb10-298"><a href="#cb10-298" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-299"><a href="#cb10-299" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>utf_16_to_8_iterator lhs, utf_16_to_8_iterator rhs<span class="op">)</span></span>
<span id="cb10-300"><a href="#cb10-300" aria-hidden="true" tabindex="-1"></a>      <span class="op">{</span> <span class="cf">return</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>base<span class="op">()</span> <span class="op">&amp;&amp;</span> lhs<span class="op">.</span>index_ <span class="op">==</span> rhs<span class="op">.</span>index_; <span class="op">}</span></span>
<span id="cb10-301"><a href="#cb10-301" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-302"><a href="#cb10-302" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>base-type</em> <span class="op">=</span>         <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-303"><a href="#cb10-303" aria-hidden="true" tabindex="-1"></a>      iterator_interface<span class="op">&lt;</span>utf_16_to_8_iterator<span class="op">&lt;</span>I, S, ErrorHandler<span class="op">&gt;</span>,</span>
<span id="cb10-304"><a href="#cb10-304" aria-hidden="true" tabindex="-1"></a>                         bidirectional_iterator_tag,</span>
<span id="cb10-305"><a href="#cb10-305" aria-hidden="true" tabindex="-1"></a>                         <span class="dt">char</span>,</span>
<span id="cb10-306"><a href="#cb10-306" aria-hidden="true" tabindex="-1"></a>                         <span class="dt">char</span><span class="op">&gt;</span>;</span>
<span id="cb10-307"><a href="#cb10-307" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>base-type</em><span class="op">::</span><span class="kw">operator</span><span class="op">++</span>;</span>
<span id="cb10-308"><a href="#cb10-308" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>base-type</em><span class="op">::</span><span class="kw">operator</span><span class="op">--</span>;</span>
<span id="cb10-309"><a href="#cb10-309" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-310"><a href="#cb10-310" aria-hidden="true" tabindex="-1"></a>  <span class="kw">private</span><span class="op">:</span></span>
<span id="cb10-311"><a href="#cb10-311" aria-hidden="true" tabindex="-1"></a>    I first_;                 <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-312"><a href="#cb10-312" aria-hidden="true" tabindex="-1"></a>    I it_;                    <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-313"><a href="#cb10-313" aria-hidden="true" tabindex="-1"></a>    S last_;                  <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-314"><a href="#cb10-314" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> index_;               <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-315"><a href="#cb10-315" aria-hidden="true" tabindex="-1"></a>    array<span class="op">&lt;</span><span class="dt">char</span>, <span class="dv">5</span><span class="op">&gt;</span> buf_;      <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-316"><a href="#cb10-316" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-317"><a href="#cb10-317" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-318"><a href="#cb10-318" aria-hidden="true" tabindex="-1"></a>      utf16_iter I2,</span>
<span id="cb10-319"><a href="#cb10-319" aria-hidden="true" tabindex="-1"></a>      sentinel_for<span class="op">&lt;</span>I2<span class="op">&gt;</span> S2,</span>
<span id="cb10-320"><a href="#cb10-320" aria-hidden="true" tabindex="-1"></a>      transcoding_error_handler ErrorHandler2<span class="op">&gt;</span></span>
<span id="cb10-321"><a href="#cb10-321" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">struct</span> utf_16_to_8_iterator;</span>
<span id="cb10-322"><a href="#cb10-322" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb10-323"><a href="#cb10-323" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-324"><a href="#cb10-324" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I, <span class="kw">class</span> S, <span class="kw">class</span> ErrorHandler<span class="op">&gt;</span></span>
<span id="cb10-325"><a href="#cb10-325" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span></span>
<span id="cb10-326"><a href="#cb10-326" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> utf_16_to_8_iterator<span class="op">&lt;</span>I, S, ErrorHandler<span class="op">&gt;&amp;</span> lhs, Sentinel rhs<span class="op">)</span></span>
<span id="cb10-327"><a href="#cb10-327" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs; <span class="op">}</span>;</span>
<span id="cb10-328"><a href="#cb10-328" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-329"><a href="#cb10-329" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-330"><a href="#cb10-330" aria-hidden="true" tabindex="-1"></a>    <span class="kw">class</span> I1, <span class="kw">class</span> S1,</span>
<span id="cb10-331"><a href="#cb10-331" aria-hidden="true" tabindex="-1"></a>    <span class="kw">class</span> I2, <span class="kw">class</span> S2,</span>
<span id="cb10-332"><a href="#cb10-332" aria-hidden="true" tabindex="-1"></a>    <span class="kw">class</span> ErrorHandler<span class="op">&gt;</span></span>
<span id="cb10-333"><a href="#cb10-333" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span></span>
<span id="cb10-334"><a href="#cb10-334" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> utf_16_to_8_iterator<span class="op">&lt;</span>I1, S1, ErrorHandler<span class="op">&gt;&amp;</span> lhs,</span>
<span id="cb10-335"><a href="#cb10-335" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> utf_16_to_8_iterator<span class="op">&lt;</span>I2, S2, ErrorHandler<span class="op">&gt;&amp;</span> rhs<span class="op">)</span></span>
<span id="cb10-336"><a href="#cb10-336" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>base<span class="op">()</span>; <span class="op">}</span>;</span>
<span id="cb10-337"><a href="#cb10-337" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-338"><a href="#cb10-338" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-339"><a href="#cb10-339" aria-hidden="true" tabindex="-1"></a>    utf8_iter I,</span>
<span id="cb10-340"><a href="#cb10-340" aria-hidden="true" tabindex="-1"></a>    sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S,</span>
<span id="cb10-341"><a href="#cb10-341" aria-hidden="true" tabindex="-1"></a>    transcoding_error_handler ErrorHandler<span class="op">&gt;</span></span>
<span id="cb10-342"><a href="#cb10-342" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_8_to_16_iterator</span>
<span id="cb10-343"><a href="#cb10-343" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> iterator_interface<span class="op">&lt;</span>utf_8_to_16_iterator<span class="op">&lt;</span>I, S, ErrorHandler<span class="op">&gt;</span>, bidirectional_iterator_tag, <span class="dt">uint16_t</span>, <span class="dt">uint16_t</span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb10-344"><a href="#cb10-344" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_16_iterator<span class="op">()</span>;</span>
<span id="cb10-345"><a href="#cb10-345" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> utf_8_to_16_iterator<span class="op">(</span>I first, I it, S last<span class="op">)</span>;</span>
<span id="cb10-346"><a href="#cb10-346" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I2, <span class="kw">class</span> S2<span class="op">&gt;</span></span>
<span id="cb10-347"><a href="#cb10-347" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> convertible_to<span class="op">&lt;</span>I2, I<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> convertible_to<span class="op">&lt;</span>S2, S<span class="op">&gt;</span></span>
<span id="cb10-348"><a href="#cb10-348" aria-hidden="true" tabindex="-1"></a>        <span class="kw">constexpr</span> utf_8_to_16_iterator<span class="op">(</span></span>
<span id="cb10-349"><a href="#cb10-349" aria-hidden="true" tabindex="-1"></a>          <span class="kw">const</span> utf_8_to_16_iterator<span class="op">&lt;</span>I2, S2, ErrorHandler<span class="op">&gt;&amp;</span> other<span class="op">)</span>;</span>
<span id="cb10-350"><a href="#cb10-350" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-351"><a href="#cb10-351" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> I begin<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> it_<span class="op">.</span>begin<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb10-352"><a href="#cb10-352" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> S end<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> it_<span class="op">.</span>end<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb10-353"><a href="#cb10-353" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-354"><a href="#cb10-354" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">uint16_t</span> <span class="kw">operator</span><span class="op">*()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> buf_<span class="op">[</span>index_<span class="op">]</span>; <span class="op">}</span></span>
<span id="cb10-355"><a href="#cb10-355" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-356"><a href="#cb10-356" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> I base<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> it_<span class="op">.</span>base<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb10-357"><a href="#cb10-357" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-358"><a href="#cb10-358" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_16_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">++()</span>;</span>
<span id="cb10-359"><a href="#cb10-359" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_16_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">--()</span>;</span>
<span id="cb10-360"><a href="#cb10-360" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-361"><a href="#cb10-361" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-362"><a href="#cb10-362" aria-hidden="true" tabindex="-1"></a>      <span class="kw">class</span> I1, <span class="kw">class</span> S1,</span>
<span id="cb10-363"><a href="#cb10-363" aria-hidden="true" tabindex="-1"></a>      <span class="kw">class</span> I2, <span class="kw">class</span> S2,</span>
<span id="cb10-364"><a href="#cb10-364" aria-hidden="true" tabindex="-1"></a>      <span class="kw">class</span> ErrorHandler2<span class="op">&gt;</span></span>
<span id="cb10-365"><a href="#cb10-365" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span></span>
<span id="cb10-366"><a href="#cb10-366" aria-hidden="true" tabindex="-1"></a>      <span class="kw">const</span> utf_8_to_16_iterator<span class="op">&lt;</span>I1, S1, ErrorHandler2<span class="op">&gt;&amp;</span> lhs,</span>
<span id="cb10-367"><a href="#cb10-367" aria-hidden="true" tabindex="-1"></a>      <span class="kw">const</span> utf_8_to_16_iterator<span class="op">&lt;</span>I2, S2, ErrorHandler2<span class="op">&gt;&amp;</span> rhs<span class="op">)</span></span>
<span id="cb10-368"><a href="#cb10-368" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>base<span class="op">()</span><span class="ch">&#39; </span><span class="er">}</span></span>
<span id="cb10-369"><a href="#cb10-369" aria-hidden="true" tabindex="-1"></a>          <span class="op">{</span> <span class="cf">return</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>base<span class="op">()</span> <span class="op">&amp;&amp;</span> lhs<span class="op">.</span>index_ <span class="op">==</span> rhs<span class="op">.</span>index_; <span class="op">}</span></span>
<span id="cb10-370"><a href="#cb10-370" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-371"><a href="#cb10-371" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>utf_8_to_16_iterator lhs, utf_8_to_16_iterator rhs<span class="op">)</span></span>
<span id="cb10-372"><a href="#cb10-372" aria-hidden="true" tabindex="-1"></a>      <span class="op">{</span> <span class="cf">return</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>base<span class="op">()</span> <span class="op">&amp;&amp;</span> lhs<span class="op">.</span>index_ <span class="op">==</span> rhs<span class="op">.</span>index_; <span class="op">}</span></span>
<span id="cb10-373"><a href="#cb10-373" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-374"><a href="#cb10-374" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>base-type</em> <span class="op">=</span>                <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-375"><a href="#cb10-375" aria-hidden="true" tabindex="-1"></a>      iterator_interface<span class="op">&lt;</span>utf_8_to_16_iterator<span class="op">&lt;</span>I, S, ErrorHandler<span class="op">&gt;</span>,</span>
<span id="cb10-376"><a href="#cb10-376" aria-hidden="true" tabindex="-1"></a>                         bidirectional_iterator_tag,</span>
<span id="cb10-377"><a href="#cb10-377" aria-hidden="true" tabindex="-1"></a>                         <span class="dt">uint16_t</span>,</span>
<span id="cb10-378"><a href="#cb10-378" aria-hidden="true" tabindex="-1"></a>                         <span class="dt">uint16_t</span><span class="op">&gt;</span>;</span>
<span id="cb10-379"><a href="#cb10-379" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>base-type</em><span class="op">::</span><span class="kw">operator</span><span class="op">++</span>;</span>
<span id="cb10-380"><a href="#cb10-380" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>base-type</em><span class="op">::</span><span class="kw">operator</span><span class="op">--</span>;</span>
<span id="cb10-381"><a href="#cb10-381" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-382"><a href="#cb10-382" aria-hidden="true" tabindex="-1"></a>  <span class="kw">private</span><span class="op">:</span></span>
<span id="cb10-383"><a href="#cb10-383" aria-hidden="true" tabindex="-1"></a>    utf_8_to_32_iterator<span class="op">&lt;</span>I, S<span class="op">&gt;</span> it_;  <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-384"><a href="#cb10-384" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> index_;                      <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-385"><a href="#cb10-385" aria-hidden="true" tabindex="-1"></a>    array<span class="op">&lt;</span><span class="dt">uint16_t</span>, <span class="dv">4</span><span class="op">&gt;</span> buf_;         <span class="co">// <em>exposition only</em></span></span>
<span id="cb10-386"><a href="#cb10-386" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-387"><a href="#cb10-387" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb10-388"><a href="#cb10-388" aria-hidden="true" tabindex="-1"></a>      utf8_iter I2,</span>
<span id="cb10-389"><a href="#cb10-389" aria-hidden="true" tabindex="-1"></a>      sentinel_for<span class="op">&lt;</span>I2<span class="op">&gt;</span> S2,</span>
<span id="cb10-390"><a href="#cb10-390" aria-hidden="true" tabindex="-1"></a>      transcoding_error_handler ErrorHandler2<span class="op">&gt;</span></span>
<span id="cb10-391"><a href="#cb10-391" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">struct</span> utf_8_to_16_iterator;</span>
<span id="cb10-392"><a href="#cb10-392" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb10-393"><a href="#cb10-393" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-394"><a href="#cb10-394" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I, <span class="kw">class</span> S, <span class="kw">class</span> ErrorHandler<span class="op">&gt;</span></span>
<span id="cb10-395"><a href="#cb10-395" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span></span>
<span id="cb10-396"><a href="#cb10-396" aria-hidden="true" tabindex="-1"></a>      <span class="kw">const</span> utf_8_to_16_iterator<span class="op">&lt;</span>I, S, ErrorHandler<span class="op">&gt;&amp;</span> lhs, Sentinel rhs<span class="op">)</span></span>
<span id="cb10-397"><a href="#cb10-397" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> lhs<span class="op">.</span>base<span class="op">()</span> <span class="op">==</span> rhs; <span class="op">}</span>;</span>
<span id="cb10-398"><a href="#cb10-398" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 data-number="4.6.2" id="add-out-and-insert-transcoding-iterators"><span class="header-section-number">4.6.2</span> Add out and insert
transcoding iterators<a href="#add-out-and-insert-transcoding-iterators" class="self-link"></a></h3>
<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><span class="kw">namespace</span> std<span class="op">::</span>uc <span class="op">{</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> D, <span class="kw">class</span> I<span class="op">&gt;</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> <em>trans-ins-iter</em> <span class="op">{</span>           <span class="co">// <em>exposition only</em></span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> value_type <span class="op">=</span> <span class="dt">void</span>;</span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> difference_type <span class="op">=</span> <span class="dt">ptrdiff_t</span>;</span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> pointer <span class="op">=</span> <span class="dt">void</span>;</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> reference <span class="op">=</span> <span class="dt">void</span>;</span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> iterator_category <span class="op">=</span> output_iterator_tag;</span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>     <span class="kw">constexpr</span> <em>trans-ins-iter</em><span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>     <span class="kw">constexpr</span> <em>trans-ins-iter</em><span class="op">(</span>I it<span class="op">)</span> <span class="op">:</span> it_<span class="op">(</span>it<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>     <span class="kw">constexpr</span> D<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">*()</span> <span class="op">{</span> <span class="cf">return</span> derived<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a>     <span class="kw">constexpr</span> D<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">++()</span> <span class="op">{</span> <span class="cf">return</span> derived<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a>     <span class="kw">constexpr</span> D <span class="kw">operator</span><span class="op">++(</span><span class="dt">int</span><span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> derived<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a>     <span class="kw">constexpr</span> I base<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> it_; <span class="op">}</span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">protected</span><span class="op">:</span></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> I<span class="op">&amp;</span> iter<span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> it_; <span class="op">}</span></span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true" tabindex="-1"></a>  <span class="kw">private</span><span class="op">:</span></span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> D<span class="op">&amp;</span> derived<span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> <span class="kw">static_cast</span><span class="op">&lt;</span>D<span class="op">&amp;&gt;(*</span><span class="kw">this</span><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true" tabindex="-1"></a>    I it_;</span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-24"><a href="#cb11-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-25"><a href="#cb11-25" aria-hidden="true" tabindex="-1"></a>  <span class="co">// UTF-32 -&gt; UTF-8</span></span>
<span id="cb11-26"><a href="#cb11-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-27"><a href="#cb11-27" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>output_iterator<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;</span> Iter<span class="op">&gt;</span></span>
<span id="cb11-28"><a href="#cb11-28" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_32_to_8_out_iterator</span>
<span id="cb11-29"><a href="#cb11-29" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_32_to_8_out_iterator<span class="op">&lt;</span>Iter<span class="op">&gt;</span>, Iter<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb11-30"><a href="#cb11-30" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_8_out_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-31"><a href="#cb11-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">explicit</span> utf_32_to_8_out_iterator<span class="op">(</span>Iter it<span class="op">)</span>;</span>
<span id="cb11-32"><a href="#cb11-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-33"><a href="#cb11-33" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_8_out_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint32_t</span> cp<span class="op">)</span>;</span>
<span id="cb11-34"><a href="#cb11-34" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-35"><a href="#cb11-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-36"><a href="#cb11-36" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Cont<span class="op">&gt;</span></span>
<span id="cb11-37"><a href="#cb11-37" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_32_to_8_insert_iterator</span>
<span id="cb11-38"><a href="#cb11-38" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_32_to_8_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;</span>, insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb11-39"><a href="#cb11-39" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_8_insert_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-40"><a href="#cb11-40" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_8_insert_iterator<span class="op">(</span>Cont<span class="op">&amp;</span> c, <span class="kw">typename</span> Cont<span class="op">::</span>iterator it<span class="op">)</span>;</span>
<span id="cb11-41"><a href="#cb11-41" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-42"><a href="#cb11-42" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_8_insert_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint32_t</span> cp<span class="op">)</span>;</span>
<span id="cb11-43"><a href="#cb11-43" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-44"><a href="#cb11-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-45"><a href="#cb11-45" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Cont<span class="op">&gt;</span></span>
<span id="cb11-46"><a href="#cb11-46" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_32_to_8_front_insert_iterator</span>
<span id="cb11-47"><a href="#cb11-47" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_32_to_8_front_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;</span>, front_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb11-48"><a href="#cb11-48" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_8_front_insert_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-49"><a href="#cb11-49" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">explicit</span> utf_32_to_8_front_insert_iterator<span class="op">(</span>Cont<span class="op">&amp;</span> c<span class="op">)</span>;</span>
<span id="cb11-50"><a href="#cb11-50" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-51"><a href="#cb11-51" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_8_front_insert_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint32_t</span> cp<span class="op">)</span>;</span>
<span id="cb11-52"><a href="#cb11-52" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-53"><a href="#cb11-53" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-54"><a href="#cb11-54" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Cont<span class="op">&gt;</span></span>
<span id="cb11-55"><a href="#cb11-55" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_32_to_8_back_insert_iterator</span>
<span id="cb11-56"><a href="#cb11-56" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_32_to_8_back_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;</span>, back_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb11-57"><a href="#cb11-57" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_8_back_insert_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-58"><a href="#cb11-58" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">explicit</span> utf_32_to_8_back_insert_iterator<span class="op">(</span>Cont<span class="op">&amp;</span> c<span class="op">)</span>;</span>
<span id="cb11-59"><a href="#cb11-59" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-60"><a href="#cb11-60" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_8_back_insert_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint32_t</span> cp<span class="op">)</span>;</span>
<span id="cb11-61"><a href="#cb11-61" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-62"><a href="#cb11-62" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-63"><a href="#cb11-63" aria-hidden="true" tabindex="-1"></a>  <span class="co">// UTF-8 -&gt; UTF-32</span></span>
<span id="cb11-64"><a href="#cb11-64" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-65"><a href="#cb11-65" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>output_iterator<span class="op">&lt;</span><span class="dt">uint32_t</span><span class="op">&gt;</span> Iter<span class="op">&gt;</span></span>
<span id="cb11-66"><a href="#cb11-66" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_8_to_32_out_iterator</span>
<span id="cb11-67"><a href="#cb11-67" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_8_to_32_out_iterator<span class="op">&lt;</span>Iter<span class="op">&gt;</span>, Iter<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb11-68"><a href="#cb11-68" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_32_out_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-69"><a href="#cb11-69" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">explicit</span> utf_8_to_32_out_iterator<span class="op">(</span>Iter it<span class="op">)</span>;</span>
<span id="cb11-70"><a href="#cb11-70" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-71"><a href="#cb11-71" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_32_out_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">char</span> cu<span class="op">)</span>;</span>
<span id="cb11-72"><a href="#cb11-72" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-73"><a href="#cb11-73" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-74"><a href="#cb11-74" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Cont<span class="op">&gt;</span></span>
<span id="cb11-75"><a href="#cb11-75" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_8_to_32_insert_iterator</span>
<span id="cb11-76"><a href="#cb11-76" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_8_to_32_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;</span>, insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb11-77"><a href="#cb11-77" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_32_insert_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-78"><a href="#cb11-78" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_32_insert_iterator<span class="op">(</span>Cont<span class="op">&amp;</span> c, <span class="kw">typename</span> Cont<span class="op">::</span>iterator it<span class="op">)</span>;</span>
<span id="cb11-79"><a href="#cb11-79" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-80"><a href="#cb11-80" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_32_insert_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint16_t</span> cu<span class="op">)</span>;</span>
<span id="cb11-81"><a href="#cb11-81" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-82"><a href="#cb11-82" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-83"><a href="#cb11-83" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Cont<span class="op">&gt;</span></span>
<span id="cb11-84"><a href="#cb11-84" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_8_to_32_front_insert_iterator</span>
<span id="cb11-85"><a href="#cb11-85" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_8_to_32_front_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;</span>, front_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb11-86"><a href="#cb11-86" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_32_front_insert_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-87"><a href="#cb11-87" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">explicit</span> utf_8_to_32_front_insert_iterator<span class="op">(</span>Cont<span class="op">&amp;</span> c<span class="op">)</span>;</span>
<span id="cb11-88"><a href="#cb11-88" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-89"><a href="#cb11-89" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_32_front_insert_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint16_t</span> cu<span class="op">)</span>;</span>
<span id="cb11-90"><a href="#cb11-90" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-91"><a href="#cb11-91" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-92"><a href="#cb11-92" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Cont<span class="op">&gt;</span></span>
<span id="cb11-93"><a href="#cb11-93" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_8_to_32_back_insert_iterator</span>
<span id="cb11-94"><a href="#cb11-94" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_8_to_32_back_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;</span>, back_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb11-95"><a href="#cb11-95" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_32_back_insert_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-96"><a href="#cb11-96" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">explicit</span> utf_8_to_32_back_insert_iterator<span class="op">(</span>Cont<span class="op">&amp;</span> c<span class="op">)</span>;</span>
<span id="cb11-97"><a href="#cb11-97" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-98"><a href="#cb11-98" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_32_back_insert_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint16_t</span> cu<span class="op">)</span>;</span>
<span id="cb11-99"><a href="#cb11-99" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-100"><a href="#cb11-100" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-101"><a href="#cb11-101" aria-hidden="true" tabindex="-1"></a>  <span class="co">// UTF-32 -&gt; UTF-16</span></span>
<span id="cb11-102"><a href="#cb11-102" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-103"><a href="#cb11-103" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>output_iterator<span class="op">&lt;</span><span class="dt">uint16_t</span><span class="op">&gt;</span> Iter<span class="op">&gt;</span></span>
<span id="cb11-104"><a href="#cb11-104" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_32_to_16_out_iterator</span>
<span id="cb11-105"><a href="#cb11-105" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_32_to_16_out_iterator<span class="op">&lt;</span>Iter<span class="op">&gt;</span>, Iter<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb11-106"><a href="#cb11-106" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_16_out_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-107"><a href="#cb11-107" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">explicit</span> utf_32_to_16_out_iterator<span class="op">(</span>Iter it<span class="op">)</span>;</span>
<span id="cb11-108"><a href="#cb11-108" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-109"><a href="#cb11-109" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_16_out_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint32_t</span> cp<span class="op">)</span>;</span>
<span id="cb11-110"><a href="#cb11-110" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-111"><a href="#cb11-111" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-112"><a href="#cb11-112" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Cont<span class="op">&gt;</span></span>
<span id="cb11-113"><a href="#cb11-113" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_32_to_16_insert_iterator</span>
<span id="cb11-114"><a href="#cb11-114" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_32_to_16_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;</span>, insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb11-115"><a href="#cb11-115" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_16_insert_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-116"><a href="#cb11-116" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_16_insert_iterator<span class="op">(</span>Cont<span class="op">&amp;</span> c, <span class="kw">typename</span> Cont<span class="op">::</span>iterator it<span class="op">)</span>;</span>
<span id="cb11-117"><a href="#cb11-117" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-118"><a href="#cb11-118" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_16_insert_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint32_t</span> cp<span class="op">)</span>;</span>
<span id="cb11-119"><a href="#cb11-119" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-120"><a href="#cb11-120" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-121"><a href="#cb11-121" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Cont<span class="op">&gt;</span></span>
<span id="cb11-122"><a href="#cb11-122" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_32_to_16_front_insert_iterator</span>
<span id="cb11-123"><a href="#cb11-123" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_32_to_16_front_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;</span>, front_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb11-124"><a href="#cb11-124" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_16_front_insert_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-125"><a href="#cb11-125" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">explicit</span> utf_32_to_16_front_insert_iterator<span class="op">(</span>Cont<span class="op">&amp;</span> c<span class="op">)</span>;</span>
<span id="cb11-126"><a href="#cb11-126" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-127"><a href="#cb11-127" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_16_front_insert_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint32_t</span> cp<span class="op">)</span>;</span>
<span id="cb11-128"><a href="#cb11-128" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-129"><a href="#cb11-129" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-130"><a href="#cb11-130" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Cont<span class="op">&gt;</span></span>
<span id="cb11-131"><a href="#cb11-131" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_32_to_16_back_insert_iterator</span>
<span id="cb11-132"><a href="#cb11-132" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_32_to_16_back_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;</span>, back_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb11-133"><a href="#cb11-133" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_16_back_insert_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-134"><a href="#cb11-134" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">explicit</span> utf_32_to_16_back_insert_iterator<span class="op">(</span>Cont<span class="op">&amp;</span> c<span class="op">)</span>;</span>
<span id="cb11-135"><a href="#cb11-135" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-136"><a href="#cb11-136" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_16_back_insert_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint32_t</span> cp<span class="op">)</span>;</span>
<span id="cb11-137"><a href="#cb11-137" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-138"><a href="#cb11-138" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-139"><a href="#cb11-139" aria-hidden="true" tabindex="-1"></a>  <span class="co">// UTF-16 -&gt; UTF-32</span></span>
<span id="cb11-140"><a href="#cb11-140" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-141"><a href="#cb11-141" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>output_iterator<span class="op">&lt;</span><span class="dt">uint32_t</span><span class="op">&gt;</span> Iter<span class="op">&gt;</span></span>
<span id="cb11-142"><a href="#cb11-142" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_16_to_32_out_iterator</span>
<span id="cb11-143"><a href="#cb11-143" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_16_to_32_out_iterator<span class="op">&lt;</span>Iter<span class="op">&gt;</span>, Iter<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb11-144"><a href="#cb11-144" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_32_out_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-145"><a href="#cb11-145" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">explicit</span> utf_16_to_32_out_iterator<span class="op">(</span>Iter it<span class="op">)</span>;</span>
<span id="cb11-146"><a href="#cb11-146" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-147"><a href="#cb11-147" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_32_out_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint16_t</span> cu<span class="op">)</span>;</span>
<span id="cb11-148"><a href="#cb11-148" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-149"><a href="#cb11-149" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-150"><a href="#cb11-150" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Cont<span class="op">&gt;</span></span>
<span id="cb11-151"><a href="#cb11-151" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_16_to_32_insert_iterator</span>
<span id="cb11-152"><a href="#cb11-152" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_16_to_32_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;</span>, insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb11-153"><a href="#cb11-153" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_32_insert_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-154"><a href="#cb11-154" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_32_insert_iterator<span class="op">(</span>Cont<span class="op">&amp;</span> c, <span class="kw">typename</span> Cont<span class="op">::</span>iterator it<span class="op">)</span>;</span>
<span id="cb11-155"><a href="#cb11-155" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-156"><a href="#cb11-156" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_32_insert_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint16_t</span> cu<span class="op">)</span>;</span>
<span id="cb11-157"><a href="#cb11-157" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-158"><a href="#cb11-158" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-159"><a href="#cb11-159" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Cont<span class="op">&gt;</span></span>
<span id="cb11-160"><a href="#cb11-160" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_16_to_32_front_insert_iterator</span>
<span id="cb11-161"><a href="#cb11-161" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_16_to_32_front_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;</span>, front_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb11-162"><a href="#cb11-162" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_32_front_insert_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-163"><a href="#cb11-163" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> utf_16_to_32_front_insert_iterator<span class="op">(</span>Cont<span class="op">&amp;</span> c<span class="op">)</span>;</span>
<span id="cb11-164"><a href="#cb11-164" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-165"><a href="#cb11-165" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_32_front_insert_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint16_t</span> cu<span class="op">)</span>;</span>
<span id="cb11-166"><a href="#cb11-166" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-167"><a href="#cb11-167" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-168"><a href="#cb11-168" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Cont<span class="op">&gt;</span></span>
<span id="cb11-169"><a href="#cb11-169" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_16_to_32_back_insert_iterator</span>
<span id="cb11-170"><a href="#cb11-170" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_16_to_32_back_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;</span>, back_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb11-171"><a href="#cb11-171" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_32_back_insert_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-172"><a href="#cb11-172" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> utf_16_to_32_back_insert_iterator<span class="op">(</span>Cont<span class="op">&amp;</span> c<span class="op">)</span>;</span>
<span id="cb11-173"><a href="#cb11-173" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-174"><a href="#cb11-174" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_32_back_insert_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint16_t</span> cu<span class="op">)</span>;</span>
<span id="cb11-175"><a href="#cb11-175" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-176"><a href="#cb11-176" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-177"><a href="#cb11-177" aria-hidden="true" tabindex="-1"></a>  <span class="co">// UTF-16 -&gt; UTF-8</span></span>
<span id="cb11-178"><a href="#cb11-178" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-179"><a href="#cb11-179" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>output_iterator<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;</span> Iter<span class="op">&gt;</span></span>
<span id="cb11-180"><a href="#cb11-180" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_16_to_8_out_iterator</span>
<span id="cb11-181"><a href="#cb11-181" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_16_to_8_out_iterator<span class="op">&lt;</span>Iter<span class="op">&gt;</span>, Iter<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb11-182"><a href="#cb11-182" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_8_out_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-183"><a href="#cb11-183" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> utf_16_to_8_out_iterator<span class="op">(</span>Iter it<span class="op">)</span>;</span>
<span id="cb11-184"><a href="#cb11-184" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-185"><a href="#cb11-185" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_8_out_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint16_t</span> cu<span class="op">)</span>;</span>
<span id="cb11-186"><a href="#cb11-186" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-187"><a href="#cb11-187" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-188"><a href="#cb11-188" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Cont<span class="op">&gt;</span></span>
<span id="cb11-189"><a href="#cb11-189" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_16_to_8_insert_iterator</span>
<span id="cb11-190"><a href="#cb11-190" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_16_to_8_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;</span>, insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb11-191"><a href="#cb11-191" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_8_insert_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-192"><a href="#cb11-192" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_8_insert_iterator<span class="op">(</span>Cont<span class="op">&amp;</span> c, <span class="kw">typename</span> Cont<span class="op">::</span>iterator it<span class="op">)</span>;</span>
<span id="cb11-193"><a href="#cb11-193" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-194"><a href="#cb11-194" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_8_insert_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint16_t</span> cu<span class="op">)</span>;</span>
<span id="cb11-195"><a href="#cb11-195" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-196"><a href="#cb11-196" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-197"><a href="#cb11-197" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Cont<span class="op">&gt;</span></span>
<span id="cb11-198"><a href="#cb11-198" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_16_to_8_front_insert_iterator</span>
<span id="cb11-199"><a href="#cb11-199" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_16_to_8_front_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;</span>, front_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb11-200"><a href="#cb11-200" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_8_front_insert_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-201"><a href="#cb11-201" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> utf_16_to_8_front_insert_iterator<span class="op">(</span>Cont<span class="op">&amp;</span> c<span class="op">)</span>;</span>
<span id="cb11-202"><a href="#cb11-202" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-203"><a href="#cb11-203" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_8_front_insert_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint16_t</span> cu<span class="op">)</span>;</span>
<span id="cb11-204"><a href="#cb11-204" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-205"><a href="#cb11-205" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-206"><a href="#cb11-206" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Cont<span class="op">&gt;</span></span>
<span id="cb11-207"><a href="#cb11-207" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_16_to_8_back_insert_iterator</span>
<span id="cb11-208"><a href="#cb11-208" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_16_to_8_back_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;</span>, back_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb11-209"><a href="#cb11-209" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_8_back_insert_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-210"><a href="#cb11-210" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> utf_16_to_8_back_insert_iterator<span class="op">(</span>Cont<span class="op">&amp;</span> c<span class="op">)</span>;</span>
<span id="cb11-211"><a href="#cb11-211" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-212"><a href="#cb11-212" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_8_back_insert_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint16_t</span> cu<span class="op">)</span>;</span>
<span id="cb11-213"><a href="#cb11-213" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-214"><a href="#cb11-214" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-215"><a href="#cb11-215" aria-hidden="true" tabindex="-1"></a>  <span class="co">// UTF-8 -&gt; UTF-16</span></span>
<span id="cb11-216"><a href="#cb11-216" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-217"><a href="#cb11-217" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>output_iterator<span class="op">&lt;</span><span class="dt">uint16_t</span><span class="op">&gt;</span> Iter<span class="op">&gt;</span></span>
<span id="cb11-218"><a href="#cb11-218" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_8_to_16_out_iterator</span>
<span id="cb11-219"><a href="#cb11-219" aria-hidden="true" tabindex="-1"></a>      <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_8_to_16_out_iterator<span class="op">&lt;</span>Iter<span class="op">&gt;</span>, Iter<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb11-220"><a href="#cb11-220" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_16_out_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-221"><a href="#cb11-221" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> utf_8_to_16_out_iterator<span class="op">(</span>Iter it<span class="op">)</span>;</span>
<span id="cb11-222"><a href="#cb11-222" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-223"><a href="#cb11-223" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_16_out_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">char</span> cu<span class="op">)</span>;</span>
<span id="cb11-224"><a href="#cb11-224" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-225"><a href="#cb11-225" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-226"><a href="#cb11-226" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Cont<span class="op">&gt;</span></span>
<span id="cb11-227"><a href="#cb11-227" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_8_to_16_insert_iterator</span>
<span id="cb11-228"><a href="#cb11-228" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_8_to_16_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;</span>, insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb11-229"><a href="#cb11-229" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_16_insert_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-230"><a href="#cb11-230" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_16_insert_iterator<span class="op">(</span>Cont<span class="op">&amp;</span> c, <span class="kw">typename</span> Cont<span class="op">::</span>iterator it<span class="op">)</span>;</span>
<span id="cb11-231"><a href="#cb11-231" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-232"><a href="#cb11-232" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_16_insert_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint16_t</span> cu<span class="op">)</span>;</span>
<span id="cb11-233"><a href="#cb11-233" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-234"><a href="#cb11-234" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-235"><a href="#cb11-235" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Cont<span class="op">&gt;</span></span>
<span id="cb11-236"><a href="#cb11-236" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_8_to_16_front_insert_iterator</span>
<span id="cb11-237"><a href="#cb11-237" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_8_to_16_front_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;</span>, front_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb11-238"><a href="#cb11-238" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_16_front_insert_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-239"><a href="#cb11-239" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> utf_8_to_16_front_insert_iterator<span class="op">(</span>Cont<span class="op">&amp;</span> c<span class="op">)</span>;</span>
<span id="cb11-240"><a href="#cb11-240" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-241"><a href="#cb11-241" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_16_front_insert_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint16_t</span> cu<span class="op">)</span>;</span>
<span id="cb11-242"><a href="#cb11-242" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-243"><a href="#cb11-243" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-244"><a href="#cb11-244" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Cont<span class="op">&gt;</span></span>
<span id="cb11-245"><a href="#cb11-245" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf_8_to_16_back_insert_iterator</span>
<span id="cb11-246"><a href="#cb11-246" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> <em>trans-ins-iter</em><span class="op">&lt;</span>utf_8_to_16_back_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;</span>, back_insert_iterator<span class="op">&lt;</span>Cont<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb11-247"><a href="#cb11-247" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_16_back_insert_iterator<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb11-248"><a href="#cb11-248" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> utf_8_to_16_back_insert_iterator<span class="op">(</span>Cont<span class="op">&amp;</span> c<span class="op">)</span>;</span>
<span id="cb11-249"><a href="#cb11-249" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-250"><a href="#cb11-250" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_16_back_insert_iterator<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="dt">uint16_t</span> cu<span class="op">)</span>;</span>
<span id="cb11-251"><a href="#cb11-251" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-252"><a href="#cb11-252" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 data-number="4.6.3" id="add-factory-functions-for-all-the-transcoding-iterators"><span class="header-section-number">4.6.3</span> Add factory functions for all
the transcoding iterators<a href="#add-factory-functions-for-all-the-transcoding-iterators" class="self-link"></a></h3>
<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><span class="kw">namespace</span> std<span class="op">::</span>uc <span class="op">{</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>output_iterator<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;</span> O<span class="op">&gt;</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_8_out_iterator<span class="op">&lt;</span>O<span class="op">&gt;</span> utf_32_to_8_out<span class="op">(</span>O it<span class="op">)</span>;</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>output_iterator<span class="op">&lt;</span><span class="dt">uint32_t</span><span class="op">&gt;</span> O<span class="op">&gt;</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_32_out_iterator<span class="op">&lt;</span>O<span class="op">&gt;</span> utf_8_to_32_out<span class="op">(</span>O it<span class="op">)</span>;</span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>output_iterator<span class="op">&lt;</span><span class="dt">uint16_t</span><span class="op">&gt;</span> O<span class="op">&gt;</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_32_to_16_out_iterator<span class="op">&lt;</span>O<span class="op">&gt;</span> utf_32_to_16_out<span class="op">(</span>O it<span class="op">)</span>;</span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>output_iterator<span class="op">&lt;</span><span class="dt">uint32_t</span><span class="op">&gt;</span> O<span class="op">&gt;</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_32_out_iterator<span class="op">&lt;</span>O<span class="op">&gt;</span> utf_16_to_32_out<span class="op">(</span>O it<span class="op">)</span>;</span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>output_iterator<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;</span> O<span class="op">&gt;</span></span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_16_to_8_out_iterator<span class="op">&lt;</span>O<span class="op">&gt;</span> utf_16_to_8_out<span class="op">(</span>O it<span class="op">)</span>;</span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>output_iterator<span class="op">&lt;</span><span class="dt">uint16_t</span><span class="op">&gt;</span> O<span class="op">&gt;</span></span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf_8_to_16_out_iterator<span class="op">&lt;</span>O<span class="op">&gt;</span> utf_8_to_16_out<span class="op">(</span>O it<span class="op">)</span>;</span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>bidirectional_iterator I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S<span class="op">&gt;</span></span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> utf8_iterator<span class="op">(</span>I first, I it, S last<span class="op">)</span>;</span>
<span id="cb12-22"><a href="#cb12-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-23"><a href="#cb12-23" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>bidirectional_iterator I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S<span class="op">&gt;</span></span>
<span id="cb12-24"><a href="#cb12-24" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> utf16_iterator<span class="op">(</span>I first, I it, S last<span class="op">)</span>;</span>
<span id="cb12-25"><a href="#cb12-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-26"><a href="#cb12-26" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>bidirectional_iterator I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S<span class="op">&gt;</span></span>
<span id="cb12-27"><a href="#cb12-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> utf32_iterator<span class="op">(</span>I first, I it, S last<span class="op">)</span>;</span>
<span id="cb12-28"><a href="#cb12-28" aria-hidden="true" tabindex="-1"></a>  </span>
<span id="cb12-29"><a href="#cb12-29" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Cont<span class="op">&gt;</span></span>
<span id="cb12-30"><a href="#cb12-30" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> <em>utf-container</em> <span class="op">=</span> <span class="co">// <em>exposition only</em></span></span>
<span id="cb12-31"><a href="#cb12-31" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="op">{</span> <span class="kw">typename</span> Cont<span class="op">::</span>value_type; <span class="op">}</span> <span class="op">&amp;&amp;</span></span>
<span id="cb12-32"><a href="#cb12-32" aria-hidden="true" tabindex="-1"></a>      utf_code_unit<span class="op">&lt;</span>Cont<span class="op">::</span>value_type<span class="op">&gt;</span>;</span>
<span id="cb12-33"><a href="#cb12-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-34"><a href="#cb12-34" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><em>utf-container</em> Cont<span class="op">&gt;</span></span>
<span id="cb12-35"><a href="#cb12-35" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> from_utf8_inserter<span class="op">(</span>Cont<span class="op">&amp;</span> c, <span class="kw">typename</span> Cont<span class="op">::</span>iterator it<span class="op">)</span>;</span>
<span id="cb12-36"><a href="#cb12-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-37"><a href="#cb12-37" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><em>utf-container</em> Cont<span class="op">&gt;</span></span>
<span id="cb12-38"><a href="#cb12-38" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> from_utf16_inserter<span class="op">(</span>Cont<span class="op">&amp;</span> c, <span class="kw">typename</span> Cont<span class="op">::</span>iterator it<span class="op">)</span>;</span>
<span id="cb12-39"><a href="#cb12-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-40"><a href="#cb12-40" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><em>utf-container</em> Cont<span class="op">&gt;</span></span>
<span id="cb12-41"><a href="#cb12-41" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> from_utf32_inserter<span class="op">(</span>Cont<span class="op">&amp;</span> c, <span class="kw">typename</span> Cont<span class="op">::</span>iterator it<span class="op">)</span>;</span>
<span id="cb12-42"><a href="#cb12-42" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-43"><a href="#cb12-43" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><em>utf-container</em> Cont<span class="op">&gt;</span></span>
<span id="cb12-44"><a href="#cb12-44" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> from_utf8_back_inserter<span class="op">(</span>Cont<span class="op">&amp;</span> c<span class="op">)</span>;</span>
<span id="cb12-45"><a href="#cb12-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-46"><a href="#cb12-46" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><em>utf-container</em> Cont<span class="op">&gt;</span></span>
<span id="cb12-47"><a href="#cb12-47" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> from_utf16_back_inserter<span class="op">(</span>Cont<span class="op">&amp;</span> c<span class="op">)</span>;</span>
<span id="cb12-48"><a href="#cb12-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-49"><a href="#cb12-49" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><em>utf-container</em> Cont<span class="op">&gt;</span></span>
<span id="cb12-50"><a href="#cb12-50" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> from_utf32_back_inserter<span class="op">(</span>Cont<span class="op">&amp;</span> c<span class="op">)</span>;</span>
<span id="cb12-51"><a href="#cb12-51" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-52"><a href="#cb12-52" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><em>utf-container</em> Cont<span class="op">&gt;</span></span>
<span id="cb12-53"><a href="#cb12-53" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> from_utf8_front_inserter<span class="op">(</span>Cont<span class="op">&amp;</span> c<span class="op">)</span>;</span>
<span id="cb12-54"><a href="#cb12-54" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-55"><a href="#cb12-55" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><em>utf-container</em> Cont<span class="op">&gt;</span></span>
<span id="cb12-56"><a href="#cb12-56" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> from_utf16_front_inserter<span class="op">(</span>Cont<span class="op">&amp;</span> c<span class="op">)</span>;</span>
<span id="cb12-57"><a href="#cb12-57" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-58"><a href="#cb12-58" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><em>utf-container</em> Cont<span class="op">&gt;</span></span>
<span id="cb12-59"><a href="#cb12-59" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> from_utf32_front_inserter<span class="op">(</span>Cont<span class="op">&amp;</span> c<span class="op">)</span>;</span>
<span id="cb12-60"><a href="#cb12-60" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="4.7" id="add-transcoding-views"><span class="header-section-number">4.7</span> Add transcoding views<a href="#add-transcoding-views" class="self-link"></a></h2>
<h3 data-number="4.7.1" id="add-the-views-proper"><span class="header-section-number">4.7.1</span> Add the views proper<a href="#add-the-views-proper" class="self-link"></a></h3>
<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="kw">namespace</span> std<span class="op">::</span>uc <span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>utf8_iter I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S <span class="op">=</span> I<span class="op">&gt;</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf8_view <span class="op">:</span> view_interface<span class="op">&lt;</span>utf8_view<span class="op">&lt;</span>I, S<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> iterator <span class="op">=</span> I;</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> sentinel <span class="op">=</span> S;</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf8_view<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf8_view<span class="op">(</span>iterator first, sentinel last<span class="op">)</span>;</span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> iterator begin<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> sentinel end<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>utf8_view lhs, utf8_view rhs<span class="op">)</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a>      <span class="op">{</span> <span class="cf">return</span> lhs<span class="op">.</span>begin<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>begin<span class="op">()</span> <span class="op">&amp;&amp;</span> lhs<span class="op">.</span>end<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>end<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> CharT, <span class="kw">class</span> Traits<span class="op">&gt;</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> basic_ostream<span class="op">&lt;</span>CharT, Traits<span class="op">&gt;&amp;</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">&lt;&lt;(</span>basic_ostream<span class="op">&lt;</span>CharT, Traits<span class="op">&gt;&amp;</span> os, utf8_view v<span class="op">)</span>;</span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a>  <span class="kw">private</span><span class="op">:</span></span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> iterator_t <span class="op">=</span> <em>unspecified</em>;          <span class="co">// <em>exposition only</em></span></span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> sentinel_t <span class="op">=</span> <em>unspecified</em>;          <span class="co">// <em>exposition only</em></span></span>
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-24"><a href="#cb13-24" aria-hidden="true" tabindex="-1"></a>    iterator_t first_;                       <span class="co">// <em>exposition only</em></span></span>
<span id="cb13-25"><a href="#cb13-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">[[</span><span class="at">no_unique_address</span><span class="op">]]</span> sentinel_t last_;  <span class="co">// <em>exposition only</em></span></span>
<span id="cb13-26"><a href="#cb13-26" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb13-27"><a href="#cb13-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-28"><a href="#cb13-28" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>utf16_iter I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S <span class="op">=</span> I<span class="op">&gt;</span></span>
<span id="cb13-29"><a href="#cb13-29" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf16_view <span class="op">:</span> view_interface<span class="op">&lt;</span>utf16_view<span class="op">&lt;</span>I, S<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb13-30"><a href="#cb13-30" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> iterator <span class="op">=</span> I;</span>
<span id="cb13-31"><a href="#cb13-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> sentinel <span class="op">=</span> S;</span>
<span id="cb13-32"><a href="#cb13-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-33"><a href="#cb13-33" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf16_view<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb13-34"><a href="#cb13-34" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf16_view<span class="op">(</span>iterator first, sentinel last<span class="op">)</span>;</span>
<span id="cb13-35"><a href="#cb13-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-36"><a href="#cb13-36" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> iterator begin<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb13-37"><a href="#cb13-37" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> sentinel end<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb13-38"><a href="#cb13-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-39"><a href="#cb13-39" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>utf16_view lhs, utf16_view rhs<span class="op">)</span></span>
<span id="cb13-40"><a href="#cb13-40" aria-hidden="true" tabindex="-1"></a>      <span class="op">{</span> <span class="cf">return</span> lhs<span class="op">.</span>begin<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>begin<span class="op">()</span> <span class="op">&amp;&amp;</span> lhs<span class="op">.</span>end<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>end<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb13-41"><a href="#cb13-41" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-42"><a href="#cb13-42" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> CharT, <span class="kw">class</span> Traits<span class="op">&gt;</span></span>
<span id="cb13-43"><a href="#cb13-43" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> basic_ostream<span class="op">&lt;</span>CharT, Traits<span class="op">&gt;&amp;</span></span>
<span id="cb13-44"><a href="#cb13-44" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">&lt;&lt;(</span>basic_ostream<span class="op">&lt;</span>CharT, Traits<span class="op">&gt;&amp;</span> os, utf16_view v<span class="op">)</span>;</span>
<span id="cb13-45"><a href="#cb13-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-46"><a href="#cb13-46" aria-hidden="true" tabindex="-1"></a>  <span class="kw">private</span><span class="op">:</span></span>
<span id="cb13-47"><a href="#cb13-47" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> iterator_t <span class="op">=</span> <em>unspecified</em>;          <span class="co">// <em>exposition only</em></span></span>
<span id="cb13-48"><a href="#cb13-48" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> sentinel_t <span class="op">=</span> <em>unspecified</em>;          <span class="co">// <em>exposition only</em></span></span>
<span id="cb13-49"><a href="#cb13-49" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-50"><a href="#cb13-50" aria-hidden="true" tabindex="-1"></a>    iterator_t first_;                       <span class="co">// <em>exposition only</em></span></span>
<span id="cb13-51"><a href="#cb13-51" aria-hidden="true" tabindex="-1"></a>    <span class="op">[[</span><span class="at">no_unique_address</span><span class="op">]]</span> sentinel_t last_;  <span class="co">// <em>exposition only</em></span></span>
<span id="cb13-52"><a href="#cb13-52" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb13-53"><a href="#cb13-53" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-54"><a href="#cb13-54" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>utf32_iter I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S <span class="op">=</span> I<span class="op">&gt;</span></span>
<span id="cb13-55"><a href="#cb13-55" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> utf32_view <span class="op">:</span> view_interface<span class="op">&lt;</span>utf32_view<span class="op">&lt;</span>I, S<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb13-56"><a href="#cb13-56" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> iterator <span class="op">=</span> I;</span>
<span id="cb13-57"><a href="#cb13-57" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> sentinel <span class="op">=</span> S;</span>
<span id="cb13-58"><a href="#cb13-58" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-59"><a href="#cb13-59" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf32_view<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb13-60"><a href="#cb13-60" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> utf32_view<span class="op">(</span>iterator first, sentinel last<span class="op">)</span>;</span>
<span id="cb13-61"><a href="#cb13-61" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-62"><a href="#cb13-62" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> iterator begin<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb13-63"><a href="#cb13-63" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> sentinel end<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb13-64"><a href="#cb13-64" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>utf32_view lhs, utf32_view rhs<span class="op">)</span></span>
<span id="cb13-65"><a href="#cb13-65" aria-hidden="true" tabindex="-1"></a>      <span class="op">{</span> <span class="cf">return</span> lhs<span class="op">.</span>begin<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>begin<span class="op">()</span> <span class="op">&amp;&amp;</span> lhs<span class="op">.</span>end<span class="op">()</span> <span class="op">==</span> rhs<span class="op">.</span>end<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb13-66"><a href="#cb13-66" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-67"><a href="#cb13-67" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> CharT, <span class="kw">class</span> Traits<span class="op">&gt;</span></span>
<span id="cb13-68"><a href="#cb13-68" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> basic_ostream<span class="op">&lt;</span>CharT, Traits<span class="op">&gt;&amp;</span></span>
<span id="cb13-69"><a href="#cb13-69" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">&lt;&lt;(</span>basic_ostream<span class="op">&lt;</span>CharT, Traits<span class="op">&gt;&amp;</span> os, utf32_view v<span class="op">)</span>;</span>
<span id="cb13-70"><a href="#cb13-70" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-71"><a href="#cb13-71" aria-hidden="true" tabindex="-1"></a>  <span class="kw">private</span><span class="op">:</span></span>
<span id="cb13-72"><a href="#cb13-72" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> iterator_t <span class="op">=</span> <em>unspecified</em>;          <span class="co">// <em>exposition only</em></span></span>
<span id="cb13-73"><a href="#cb13-73" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> sentinel_t <span class="op">=</span> <em>unspecified</em>;          <span class="co">// <em>exposition only</em></span></span>
<span id="cb13-74"><a href="#cb13-74" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-75"><a href="#cb13-75" aria-hidden="true" tabindex="-1"></a>    iterator_t first_;                       <span class="co">// <em>exposition only</em></span></span>
<span id="cb13-76"><a href="#cb13-76" aria-hidden="true" tabindex="-1"></a>    <span class="op">[[</span><span class="at">no_unique_address</span><span class="op">]]</span> sentinel_t last_;  <span class="co">// <em>exposition only</em></span></span>
<span id="cb13-77"><a href="#cb13-77" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb13-78"><a href="#cb13-78" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb13-79"><a href="#cb13-79" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-80"><a href="#cb13-80" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb13-81"><a href="#cb13-81" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I, <span class="kw">class</span> S<span class="op">&gt;</span></span>
<span id="cb13-82"><a href="#cb13-82" aria-hidden="true" tabindex="-1"></a>    <span class="kw">inline</span> <span class="kw">constexpr</span> <span class="dt">bool</span> enable_borrowed_range<span class="op">&lt;</span>uc<span class="op">::</span>utf8_view<span class="op">&lt;</span>I, S<span class="op">&gt;&gt;</span> <span class="op">=</span> <span class="kw">true</span>;</span>
<span id="cb13-83"><a href="#cb13-83" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-84"><a href="#cb13-84" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I, <span class="kw">class</span> S<span class="op">&gt;</span></span>
<span id="cb13-85"><a href="#cb13-85" aria-hidden="true" tabindex="-1"></a>    <span class="kw">inline</span> <span class="kw">constexpr</span> <span class="dt">bool</span> enable_borrowed_range<span class="op">&lt;</span>uc<span class="op">::</span>utf16_view<span class="op">&lt;</span>I, S<span class="op">&gt;&gt;</span> <span class="op">=</span> <span class="kw">true</span>;</span>
<span id="cb13-86"><a href="#cb13-86" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-87"><a href="#cb13-87" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I, <span class="kw">class</span> S<span class="op">&gt;</span></span>
<span id="cb13-88"><a href="#cb13-88" aria-hidden="true" tabindex="-1"></a>    <span class="kw">inline</span> <span class="kw">constexpr</span> <span class="dt">bool</span> enable_borrowed_range<span class="op">&lt;</span>uc<span class="op">::</span>utf32_view<span class="op">&lt;</span>I, S<span class="op">&gt;&gt;</span> <span class="op">=</span> <span class="kw">true</span>;</span>
<span id="cb13-89"><a href="#cb13-89" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 data-number="4.7.2" id="add-as_utfn"><span class="header-section-number">4.7.2</span> Add
<code class="sourceCode default">as_utfN()</code><a href="#add-as_utfn" class="self-link"></a></h3>
<p>Each <code class="sourceCode default">as_utfN()</code> factory
function takes an iterator/sentinel pair, or a range-like (meaning an
range or a null-terminated pointer), and returns a
<code class="sourceCode default">utfN_view</code> that may do
transcoding (if the inputs are not UTF-N) or may not do transcoding (if
the inputs are UTF-N).</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><span class="kw">namespace</span> std<span class="op">::</span>uc <span class="op">{</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>utf_iter I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S<span class="op">&gt;</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <em>unspecified</em> as_utf8<span class="op">(</span>I first, S last<span class="op">)</span>;</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>utf_range_like R<span class="op">&gt;</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <em>unspecified</em> as_utf8<span class="op">(</span>R<span class="op">&amp;&amp;</span> r<span class="op">)</span>;</span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>utf_iter I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S<span class="op">&gt;</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <em>unspecified</em> as_utf16<span class="op">(</span>I first, S last<span class="op">)</span>;</span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>utf_range_like R<span class="op">&gt;</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <em>unspecified</em> as_utf16<span class="op">(</span>R<span class="op">&amp;&amp;</span> r<span class="op">)</span>;</span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>utf_iter I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S<span class="op">&gt;</span></span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <em>unspecified</em> as_utf32<span class="op">(</span>I first, S last<span class="op">)</span>;</span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>utf_range_like R<span class="op">&gt;</span></span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <em>unspecified</em> as_utf32<span class="op">(</span>R<span class="op">&amp;&amp;</span> r<span class="op">)</span>;</span>
<span id="cb14-19"><a href="#cb14-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 data-number="4.7.3" id="add-utfn_view-specializations-of-formatter"><span class="header-section-number">4.7.3</span> Add
<code class="sourceCode default">utfN_view</code> specializations of
<code class="sourceCode default">formatter</code><a href="#add-utfn_view-specializations-of-formatter" class="self-link"></a></h3>
<p>These should be added to the list of “the debug-enabled string type
specializations” in [format.formatter.spec]. This allows all three kinds
of UTF views to be used in
<code class="sourceCode default">std::format()</code> and
<code class="sourceCode default">std::print()</code>. The intention is
that each one will transcode to UTF-8 if the formatter’s
<code class="sourceCode default">charT</code> is
<code class="sourceCode default">char</code>, or to UTF-16 if the
formatter’s <code class="sourceCode default">charT</code> is
<code class="sourceCode default">wchar_t</code> – if transcoding is
necessary at all.</p>
<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">template</span><span class="op">&lt;</span><span class="kw">class</span> I, <span class="kw">class</span> S<span class="op">&gt;</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> formatter<span class="op">&lt;</span>uc<span class="op">::</span>utf8_view<span class="op">&lt;</span>I, S<span class="op">&gt;</span>, charT<span class="op">&gt;</span>;</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I, <span class="kw">class</span> S<span class="op">&gt;</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> formatter<span class="op">&lt;</span>uc<span class="op">::</span>utf16_view<span class="op">&lt;</span>I, S<span class="op">&gt;</span>, charT<span class="op">&gt;</span>;</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I, <span class="kw">class</span> S<span class="op">&gt;</span></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> formatter<span class="op">&lt;</span>uc<span class="op">::</span>utf32_view<span class="op">&lt;</span>I, S<span class="op">&gt;</span>, charT<span class="op">&gt;</span>;</span></code></pre></div>
<h2 data-number="4.8" id="add-a-feature-test-macro"><span class="header-section-number">4.8</span> Add a feature test macro<a href="#add-a-feature-test-macro" class="self-link"></a></h2>
<p>Add the feature test macro
<code class="sourceCode default">__cpp_lib_unicode_transcoding</code>.</p>
<h2 data-number="4.9" id="design-notes"><span class="header-section-number">4.9</span> Design notes<a href="#design-notes" class="self-link"></a></h2>
<p>None of the proposed interfaces is subject to change in future
versions of Unicode; each relates to the guaranteed-stable subset. Just
sayin’.</p>
<p>None of the proposed interfaces allocates.</p>
<p>The proposed interfaces allow users to choose amongst multiple
convenience-vs-compatibility-vs-performance tradeoffs. Explicitly, they
are:</p>
<ul>
<li>If you need maximum performance, stick to the transcoding
algorithms, and in particular use pointers for input and output.</li>
<li>If you need compatibility with existing iterator-based algorithms
(such as the standard algorithms), use the transcoding iterators.</li>
<li>If you want streamability or the convenience of constructing ranges
with a single <code class="sourceCode default">as_utfN()</code> function
call, use the transcoding views.</li>
</ul>
<p>All the transcoding iterators allow you access to the underlying
iterator via <code class="sourceCode default">.base()</code>, following
the convention of the iterator adaptors already in the standard.</p>
<p>The transcoding views are lazy, as you’d expect. They also compose
with the standard view adaptors, so just transcoding at most 10 UTF-16
code units out of some UTF can be done with <code class="sourceCode default">std::uc::as_utf16(foo) | std::ranges::views::take(10)</code>.</p>
<p>Error handling is explicitly configurable in the transcoding
iterators. This gives complete control to those who want to do something
other than the default. The default, according to Unicode, is to produce
a replacement character (<code class="sourceCode default">0xfffd</code>)
in the output when broken UTF encoding is seen in the input. This is
what all these interfaces do, unless you configure one of the iterators
as mentioned above.</p>
<p>The production of replacement characters as error-handling strategy
is good for memory compactness and safety. It allows use to store all
our text as UTF-8 (or, less compactly, as UTF-16), and then process code
points as transcoding views. If an error occurs, the transcoding views
will simply produce a replacement character; there is no danger of
UB.</p>
<p>Code units are just numbers. All of these interfaces treat integral
types as code units of various sizes (at least the ones that are 8-,
16-, or 32-bit). Signedness is ignored.</p>
<p>A null-terminated pointer <code class="sourceCode default">p</code>
to an 8-, 16-, or 32-bit string of code units is considered the implicit
range <code class="sourceCode default">[p, null_sentinel)</code>. This
makes user code much more natural;
<code class="sourceCode default">as_utf16(&quot;foo&quot;)</code>,
<code class="sourceCode default">as_utf16(&quot;foo&quot;sv)</code>, and
<code class="sourceCode default">as_utf16(&quot;foo&quot;s)</code> are
roughly equivalent (though the iterator type of the resulting view may
differ).</p>
<p>Iterators are constructed from more than one underlying iterator. To
do iteration in many text-handling contexts, you need to know the
beginning and the end of the range you are iterating over, just to be
able to do iteration correctly. Note that this is not a safety issue,
but a correctness one. For example, say we have a string
<code class="sourceCode default">s</code> of UTF-8 code units that we
would like to iterate over to produce UTF-32 code points. If the last
code unit in <code class="sourceCode default">s</code> is
<code class="sourceCode default">0xe0</code>, we should expect two more
code units to follow. They are not present, though, because
<code class="sourceCode default">0xe0</code> is the last code unit. Now
consider how you would implement
<code class="sourceCode default">operator++()</code> for an iterator
<code class="sourceCode default">iter</code> that transcodes from UTF-8
to UTF-32. If you advance far enough to get the next UTF-32 code point
in each call to <code class="sourceCode default">operator++()</code>,
you may run off the end of <code class="sourceCode default">s</code>
when you find <code class="sourceCode default">0xe0</code> and try to
read two more code units. Note that it does not matter that
<code class="sourceCode default">iter</code> probably comes from a range
with an end-iterator or sentinel as its mate; inside
<code class="sourceCode default">iter</code>’s
<code class="sourceCode default">operator++()</code> this is no help.
<code class="sourceCode default">iter</code> must therefore have the
end-iterator or sentinel as a data member. The same logic applies to the
other end of the range if <code class="sourceCode default">iter</code>
is bidirectional — it must also have the iterator to the start of the
underlying range as a data member. This unfortunate reality comes up
over and over in the proposed iterators, not just the ones that are UTF
transcoding iterators. This is why iterators in this proposal (and the
ones to come) usually consist of three underlying iterators.</p>
<h3 data-number="4.9.1" id="iterator-unpacking"><span class="header-section-number">4.9.1</span> Iterator “unpacking”<a href="#iterator-unpacking" class="self-link"></a></h3>
<p>A simple way to represent a transcoding view is as a pair of
transcoding iterators. However, there is a problem with that approach,
since a <code class="sourceCode default">utf32_view&lt;utf_8_to_32_iterator&lt;char const *&gt;&gt;</code>
would be a range the size of 6 pointers. Worse yet, a <code class="sourceCode default">utf32_view&lt;utf_8_to_16_iterator&lt;utf_16_to_32_iterator&lt;char const *&gt;&gt;&gt;</code>
would be the size of 18 pointers! Further, such a view would do a UTF-8
to UTF-16 to UTF-32 conversion, when it could have done a direct UTF-8
to UTF-32 conversion instead.</p>
<p>To solve these kinds of problems,
<code class="sourceCode default">as_utfN()</code> unpacks the iterators
it is given, so that only the bottom-most underlying pointer or iterator
is stored:</p>
<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>std<span class="op">::</span>string str <span class="op">=</span> <span class="st">&quot;some text&quot;</span>;</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> to_16_first <span class="op">=</span> std<span class="op">::</span>uc<span class="op">::</span>utf_8_to_16_iterator<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">::</span>iterator<span class="op">&gt;(</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>    str<span class="op">.</span>begin<span class="op">()</span>, str<span class="op">.</span>begin<span class="op">()</span>, str<span class="op">.</span>end<span class="op">())</span>;</span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> to_16_last <span class="op">=</span> std<span class="op">::</span>uc<span class="op">::</span>utf_8_to_16_iterator<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">::</span>iterator<span class="op">&gt;(</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>    str<span class="op">.</span>begin<span class="op">()</span>, str<span class="op">.</span>end<span class="op">()</span>, str<span class="op">.</span>end<span class="op">())</span>;</span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> to_32_first <span class="op">=</span> std<span class="op">::</span>uc<span class="op">::</span>utf_16_to_32_iterator<span class="op">&lt;</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>uc<span class="op">::</span>utf_8_to_16_iterator<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">::</span>iterator<span class="op">&gt;</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;(</span>to_16_first, to_16_first, to_16_last<span class="op">)</span>;</span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> to_32_last <span class="op">=</span> std<span class="op">::</span>uc<span class="op">::</span>utf_16_to_32_iterator<span class="op">&lt;</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>uc<span class="op">::</span>utf_8_to_16_iterator<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">::</span>iterator<span class="op">&gt;</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;(</span>to_16_first, to_16_last, to_16_last<span class="op">)</span>;</span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> range <span class="op">=</span> std<span class="op">::</span>uc<span class="op">::</span>as_utf8<span class="op">(</span>to_32_first, to_32_last<span class="op">)</span>;</span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a><span class="co">// Poof!  The utf_16_to_32_iterators disappeared!</span></span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>is_same<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>range<span class="op">)</span>,</span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a>                           std<span class="op">::</span>uc<span class="op">::</span>utf8_view<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">::</span>iterator<span class="op">&gt;&gt;::</span>value, <span class="st">&quot;&quot;</span><span class="op">)</span>;</span></code></pre></div>
<p>Each of these views stores only the unpacked iterator and sentinel,
so each view is typically the size of two pointers, and possibly smaller
if a sentinel is used.</p>
<p>The same unpacking logic is used in
<code class="sourceCode default">utfN_iterator()</code>,
<code class="sourceCode default">from_utfN_inserter()</code>, the
transcoding algorithms, and the normalization algorithms. This allows
you to write
<code class="sourceCode default">std::uc::as_utf32(first, last)</code>
in a generic context, without caring whether first and last are
iterators to a sequence of UTF-8, UTF-16, or UTF-32. You also do not
need to care about whether first and last are raw pointers, some other
kind of iterator, or transcoding iterators. For example, if first is a
<code class="sourceCode default">utf_32_to_8_iterator</code>, the
resulting view will use
<code class="sourceCode default">first.base()</code> for its
begin-iterator.</p>
<p>Sometimes, an interface might accept any UTF-N iterator, and then
transcode internally to UTF-32:</p>
<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">template</span><span class="op">&lt;</span>input_iterator I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S, output_iterator<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;</span> O<span class="op">&gt;</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span><span class="op">(</span>utf8_code_unit<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span> <span class="op">||</span> utf16_code_unit<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;)</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>transcode_result<span class="op">&lt;</span>I, O<span class="op">&gt;</span> transcode_to_utf32<span class="op">(</span>I first, S last, O out<span class="op">)</span>;</span></code></pre></div>
<p>For such interfaces, it can be difficult in the general case to form
an iterator of type <code class="sourceCode default">I</code> to return
to the user:</p>
<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><span class="kw">template</span><span class="op">&lt;</span>input_iterator I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S, output_iterator<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;</span> O<span class="op">&gt;</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span>utf8_code_unit<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span> <span class="op">||</span> utf16_code_unit<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;)</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>transcode_result<span class="op">&lt;</span>I, O<span class="op">&gt;</span> transcode_to_utf32<span class="op">(</span>I first, S last, O out<span class="op">)</span> <span class="op">{</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Get the input as UTF-32.</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> r <span class="op">=</span> uc<span class="op">::</span>as_utf32<span class="op">(</span>first, last<span class="op">)</span>;</span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Do transcoding.</span></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> copy_result <span class="op">=</span> ranges<span class="op">::</span>copy<span class="op">(</span>r, out<span class="op">)</span>;</span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Return an in_out_result.</span></span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> result<span class="op">&lt;</span>I, O<span class="op">&gt;{</span><span class="co">/* ??? */</span>, copy_result<span class="op">.</span>out<span class="op">}</span>;</span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>What should we write for
<code class="sourceCode default">/* ??? */</code>? That is, how do we
get back from the UTF-32 iterator
<code class="sourceCode default">r.begin()</code> to an
<code class="sourceCode default">I</code> iterator? It’s harder than it
first seems; consider the case where
<code class="sourceCode default">I</code> is <code class="sourceCode default">std::uc::utf_16_to_32_iterator&lt;std::uc::utf_8_to_16_iterator&lt;std::string::iterator&gt;&gt;</code>.
The solution is for the unpacking algorithm to remember the structure of
whatever iterator it unpacks, and then rebuild the structure when
returning the result. To demonstrate, here is the implementation of from
<code class="sourceCode default">transcode_to_utf32</code> from
Boost.Text:</p>
<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><span class="kw">template</span><span class="op">&lt;</span>std<span class="op">::</span>input_iterator I, std<span class="op">::</span>sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S, std<span class="op">::</span>output_iterator<span class="op">&lt;</span><span class="dt">uint32_t</span><span class="op">&gt;</span> O<span class="op">&gt;</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span>utf8_code_unit<span class="op">&lt;</span>std<span class="op">::</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span> <span class="op">||</span> utf16_code_unit<span class="op">&lt;</span>std<span class="op">::</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;)</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>transcode_result<span class="op">&lt;</span>I, O<span class="op">&gt;</span> transcode_to_utf32<span class="op">(</span>I first, S last, O out<span class="op">)</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> <span class="kw">const</span> r <span class="op">=</span> detail<span class="op">::</span>unpack_iterator_and_sentinel<span class="op">(</span>first, last<span class="op">)</span>;</span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> unpacked <span class="op">=</span></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>        detail<span class="op">::</span>transcode_to_32<span class="op">&lt;</span><span class="kw">false</span><span class="op">&gt;(</span>r<span class="op">.</span>tag_, r<span class="op">.</span>f_, r<span class="op">.</span>l_, <span class="op">-</span><span class="dv">1</span>, out<span class="op">)</span>;</span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">{</span>r<span class="op">.</span>repack_<span class="op">(</span>unpacked<span class="op">.</span>in<span class="op">)</span>, unpacked<span class="op">.</span>out<span class="op">}</span>;</span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If this all sounds way too complicated, it’s not that bad at all.
Here’s the unpacking/repacking implementation from Boost.Text: <a href="https://github.com/tzlaine/text/blob/master/include/boost/text/detail/unpack.hpp">unpack.hpp</a>.</p>
<h1 data-number="5" id="implementation-experience"><span class="header-section-number">5</span> Implementation experience<a href="#implementation-experience" class="self-link"></a></h1>
<p>All the interfaces proposed here have been implemented, and
re-implemented, several times over the last 5 years or so. They are part
of a proposed (but not yet accepted!) Boost library, <a href="https://github.com/tzlaine/text">Boost.Text</a>.</p>
<p>The library has hundreds of stars, though I’m not sure how many users
that equates to. All of the interfaces proposed here are among the
best-exercised in the library. There are comprehensive tests for all the
proposed entities, and those entities are used as the foundation upon
which all the other library entities are composed.</p>
<p>Though there are a lot of individual entities proposed here, at one
time or another I have need each one of them, though maybe not in every
UTF-N -&gt; UTF-M permutation. Those transcoding permutations are there
mostly for completeness. I have only ever needed UTF-8 &lt;-&gt;
UTF-&gt;32 in any of my work that uses Unicode. Frequent Windows users
will also need to convert to and from UTF-16 sometimes, because that is
the UTF that the OS APIs use.</p>
<h1 data-number="6" id="performance"><span class="header-section-number">6</span> Performance<a href="#performance" class="self-link"></a></h1>
<p>The performance situation for UTF transcoding is complicated, and so
bears some discussion. All the charts below were generated using Google
Benchmark, built with GCC on Linux.</p>
<h2 data-number="6.1" id="utf-8-to-utf-16"><span class="header-section-number">6.1</span> UTF-8 to UTF-16<a href="#utf-8-to-utf-16" class="self-link"></a></h2>
<p>Here are the relative timings for UTF-8 to UTF-16 transcoding, using
various methods (smaller is better). The input was around half a
megabyte of text from Wikipedia. “Iterators” is using
<code class="sourceCode default">std::copy</code> from
<code class="sourceCode default">utf_8_to_16_iterator</code> to a
pointer; “Algorithm
<code class="sourceCode default">std::back_inserter</code>” is using
<code class="sourceCode default">transcode_to_utf16()</code> in the SIMD
code path, and outputting to a
<code class="sourceCode default">std::back_insert_iterator</code>;
“Algorithm using SIMD” is using
<code class="sourceCode default">transcode_to_utf16()</code> from
pointer to pointer in the SIMD-using code path; “Algorithm no SIMD” is
using <code class="sourceCode default">transcode_to_utf16()</code> from
pointer to pointer in the non-SIMD code path; and “ICU” is is using
<code class="sourceCode default">UnicodeString::fromUTF8()</code>.</p>
<p><?xml version="1.0" encoding="UTF-8" standalone="no" ?> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="500" height="150">     <rect width="160.13028" height="20" y="0" fill="#32a852"></rect>     <text x="165.13028" y="10.0" dy=".35em" fill="black">Iterators</text>     <rect width="90.00108" height="20" y="25" fill="#3f6078"></rect>     <text x="95.00108" y="35.0" dy=".35em" fill="black">Algorithm std::back_inserter</text>     <rect width="56.72772" height="20" y="50" fill="#ad3939"></rect>     <text x="61.72772" y="60.0" dy=".35em" fill="black">Algorithm using SIMD</text>     <rect width="70.77636" height="20" y="75" fill="#ad9e39"></rect>     <text x="75.77636" y="85.0" dy=".35em" fill="black">Algorithm no SIMD</text>     <rect width="57.12672" height="20" y="100" fill="#ba45cc"></rect>     <text x="62.12672" y="110.0" dy=".35em" fill="black">ICU</text>     <rect width="300" height="20" y="125" fill="white"></rect>     <line x1="1" y1="129" x2="300" y2="129" stroke="black" fill="black"></line>     <line x1="1" y1="124" x2="1" y2="134" stroke="black" fill="black"></line>     <line x1="300" y1="124" x2="300" y2="134" stroke="black" fill="black"></line>     <text x="0" y="144.0" dy=".35em" fill="black">0 ns</text>     <text x="300" y="144.0" dy=".35em" text-anchor="end" fill="black">2500000 ns</text> </svg></p>
<p>The ICU performance is shown as something of a baseline, given the
ubiquity of ICU’s use in Unicode-aware programs. Note that ICU does not
have convenient APIs for doing transcoding to any format but UTF-16.</p>
<p>There are some take-always from this chart (and in fact all the other
transcoding data):</p>
<ul>
<li>The use of SIMD instructions is helpful, but not critical.</li>
<li>The use of back-inserters is quite bad for performance.</li>
<li>The transcoding iterators are terrible for performance.</li>
<li>All the above only apply to transcode-only operations; more
complicated operations that involve a transcoding step are often fairly
insensitive to transcoding performance.</li>
<li>The fastest API proposed is as fast as the equivalent ICU API.</li>
</ul>
<p>A major reason for the performance differences is that the fastest
algorithms are able to write out chunks of their results all in one go
(up to 16 at once in the SIMD paths of the transcode algorithms).
Needing to branch on each output code unit as in the “Iterators” and
“Algorithm <code class="sourceCode default">std::back_inserter</code>”
cases is much slower. One implication of this is that if you’re doing a
lot of work with each code unit or code point produced, you’re probably
doing a lot of branching in the work, and so the gains of using the
high-performance methods above will be lost. Specifically, passing
transcoding iterators to complicated Unicode algorithms like the
Bidirectional Algorithm do not result in much (if any) performance
loss.</p>
<h2 data-number="6.2" id="utf-8-to-utf-32"><span class="header-section-number">6.2</span> UTF-8 to UTF-32<a href="#utf-8-to-utf-32" class="self-link"></a></h2>
<p>These are relative timings for UTF-8 to UTF-32 transcoding. It is in
the same scale as the chart above.</p>
<p><?xml version="1.0" encoding="UTF-8" standalone="no" ?> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="500" height="125">     <rect width="99.09804" height="20" y="0" fill="#32a852"></rect>     <text x="104.09804" y="10.0" dy=".35em" fill="black">Iterators</text>     <rect width="100.27296" height="20" y="25" fill="#3f6078"></rect>     <text x="105.27296" y="35.0" dy=".35em" fill="black">Algorithm std::back_inserter</text>     <rect width="40.50972" height="20" y="50" fill="#ad3939"></rect>     <text x="45.50972" y="60.0" dy=".35em" fill="black">Algorithm using SIMD</text>     <rect width="54.67824" height="20" y="75" fill="#ad9e39"></rect>     <text x="59.67824" y="85.0" dy=".35em" fill="black">Algorithm no SIMD</text>     <rect width="300" height="20" y="100" fill="white"></rect>     <line x1="1" y1="104" x2="300" y2="104" stroke="black" fill="black"></line>     <line x1="1" y1="99" x2="1" y2="109" stroke="black" fill="black"></line>     <line x1="300" y1="99" x2="300" y2="109" stroke="black" fill="black"></line>     <text x="0" y="119.0" dy=".35em" fill="black">0 ns</text>     <text x="300" y="119.0" dy=".35em" text-anchor="end" fill="black">2500000 ns</text> </svg></p>
<p>Again, you can see very similar relationships among the different
transcoding methods, except that the iterator method is a lot
faster.</p>
<p>Note that the SIMD algorithm is quite fast. It — and all the SIMD
code — was originally developed by Bob Steagall, and presented at C++Now
in 2018. Thanks, Bob!</p>
<h1 data-number="7" id="bibliography"><span class="header-section-number">7</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-P1629R1" class="csl-entry" role="doc-biblioentry">
[P1629R1] JeanHeyd Meneide. 2020-03-02. Transcoding the world - Standard
Text Encoding. <a href="https://wg21.link/p1629r1"><div class="csl-block">https://wg21.link/p1629r1</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
