<!DOCTYPE html>
<html>
<head>
  <meta charset=UTF-8 /><meta name=viewport content="width=device-width, initial-scale=1"/><link rel=preconnent href=https://fonts.googleapis.com />
  <link rel=preconnent href=https://fonts.gstatic.com crossorigin/>
  <link rel=stylesheet href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@300..700&family=Noto+Sans:ital,wght@0,100..900;1,100..900&family=Noto+Serif:ital,wght@0,100..900;1,100..900&display=swap"/>
  <style>
html {
    --sans-serif-family: "Noto Sans", sans-serif;
    --serif-family: "Noto Serif", serif;
    --monospace-family: "Fira Code", monospace;

    --light-background-color: white;
    --light-deep-background-color: #fafafa;
    --light-text-color: black;
    --light-border-color: #aaa;
    --light-table-border-color: #777;
    --light-del-color: #be1621;
    --light-del-background-color: #fbe6e8;
    --light-ins-color: #17752d;
    --light-ins-background-color: #e4faea;
    --light-para-color: rgb(10, 73, 136);
    --light-a-color: rgb(10, 73, 136);
    --light-a-visited-color: rgb(44, 10, 136);
    --light-a-hover-color: rgb(15, 93, 170);
    --light-mark-color: black;
    --light-mark-background-color: #ffff85;
    --light-abstract-border-color: #707070;
    --light-abstract-background-color: #f0f0f0;
    --light-abstract-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23707070"><path d="M660-160h40v-160h-40v160Zm20-200q8 0 14-6t6-14q0-8-6-14t-14-6q-8 0-14 6t-6 14q0 8 6 14t14 6ZM200-800v640-640 200-200Zm80 400h147q11-23 25.5-43t32.5-37H280v80Zm0 160h123q-3-20-3-40t3-40H280v80ZM200-80q-33 0-56.5-23.5T120-160v-640q0-33 23.5-56.5T200-880h320l240 240v92q-19-6-39-9t-41-3v-40H480v-200H200v640h227q11 23 25.5 43T485-80H200Zm480-400q83 0 141.5 58.5T880-280q0 83-58.5 141.5T680-80q-83 0-141.5-58.5T480-280q0-83 58.5-141.5T680-480Z"/></svg>');
    --light-blockquote-border-color: #707070;
    --light-blockquote-background-color: #f0f0f0;
    --light-blockquote-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="%23707070"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M7.17 17c.51 0 .98-.29 1.2-.74l1.42-2.84c.14-.28.21-.58.21-.89V8c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h2l-1.03 2.06c-.45.89.2 1.94 1.2 1.94zm10 0c.51 0 .98-.29 1.2-.74l1.42-2.84c.14-.28.21-.58.21-.89V8c0-.55-.45-1-1-1h-4c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h2l-1.03 2.06c-.45.89.2 1.94 1.2 1.94z"/></svg>');
    --light-bug-block-border-color: #9f7b5d;
    --light-bug-block-background-color: #f0e2d9;
    --light-bug-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%239f7b5d"><path d="M480-120q-64 0-114.5-33T283-240l-95 54-40-69 103-60q-3-11-5-22.5t-4-22.5H120v-80h122q2-12 4-23.5t5-22.5l-103-60 40-69 94 55q8-14 18.5-27.5T322-612q-2-7-2-14v-14q0-24 7-46t19-41l-66-66 56-57 70 68q17-9 35.5-13.5T480-800q20 0 39 5t36 14l69-69 56 57-66 66q12 19 18.5 41t6.5 46v13.5q0 6.5-2 13.5 11 11 21.5 25t18.5 28l95-54 40 69-104 59q3 11 5.5 22.5T718-440h122v80H718q-2 12-4 23.5t-5 22.5l103 60-40 69-95-55q-32 54-82.5 87T480-120Zm-76-546q17-7 36.5-10.5T480-680q20 0 38.5 3t35.5 10q-8-23-28-38t-46-15q-26 0-47 15.5T404-666Zm76 466q73 0 116.5-61T640-400q0-70-40.5-135T480-600q-78 0-119 64.5T320-400q0 78 43.5 139T480-200Zm-40-80v-240h80v240h-80Z"/></svg>');
    --light-decision-block-border-color: #ab6fa2;
    --light-decision-block-background-color: #f4e6f4;
    --light-decision-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23ab6fa2"><path d="M160-120v-80h480v80H160Zm226-194L160-540l84-86 228 226-86 86Zm254-254L414-796l86-84 226 226-86 86Zm184 408L302-682l56-56 522 522-56 56Z"/></svg>');
    --light-del-block-border-color: #be1621;
    --light-del-block-background-color: #fbe6e8;
    --light-del-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23be1621"><path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z"/></svg>');
    --light-details-border-color: #707070;
    --light-details-background-color: #f0f0f0;
    --light-details-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23707070"><path d="M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>');
    --light-diff-block-border-color: #707070;
    --light-diff-block-background-color: #f0f0f0;
    --light-diff-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23707070"><path d="M500-520h80v-80h80v-80h-80v-80h-80v80h-80v80h80v80Zm-80 160h240v-80H420v80ZM320-200q-33 0-56.5-23.5T240-280v-560q0-33 23.5-56.5T320-920h280l240 240v400q0 33-23.5 56.5T760-200H320Zm0-80h440v-360L560-840H320v560ZM160-40q-33 0-56.5-23.5T80-120v-560h80v560h440v80H160Zm160-240v-560 560Z"/></svg>');
    --light-example-block-border-color: #6f8aab;
    --light-example-block-background-color: #e6e9f4;
    --light-example-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%236f8aab"><path d="M300-80q-58 0-99-41t-41-99v-520q0-58 41-99t99-41h500v600q-25 0-42.5 17.5T740-220q0 25 17.5 42.5T800-160v80H300Zm-60-267q14-7 29-10t31-3h20v-440h-20q-25 0-42.5 17.5T240-740v393Zm160-13h320v-440H400v440Zm-160 13v-453 453Zm60 187h373q-6-14-9.5-28.5T660-220q0-16 3-31t10-29H300q-26 0-43 17.5T240-220q0 26 17 43t43 17Z"/></svg>');
    --light-important-block-border-color: #b05252;
    --light-important-block-background-color: #f4e6e6;
    --light-important-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23ab6f6f"><path d="M480-120q-33 0-56.5-23.5T400-200q0-33 23.5-56.5T480-280q33 0 56.5 23.5T560-200q0 33-23.5 56.5T480-120Zm-80-240v-480h160v480H400Z"/></svg>');
    --light-ins-block-border-color: #17752d;
    --light-ins-block-background-color: #e4faea;
    --light-ins-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%2317752d"><path d="M440-240h80v-120h120v-80H520v-120h-80v120H320v80h120v120ZM240-80q-33 0-56.5-23.5T160-160v-640q0-33 23.5-56.5T240-880h320l240 240v480q0 33-23.5 56.5T720-80H240Zm280-520v-200H240v640h480v-440H520ZM240-800v200-200 640-640Z"/></svg>');
    --light-note-block-border-color: #6fab6f;
    --light-note-block-background-color: #e6f4e9;
    --light-note-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%236fab6f"><path d="M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>');
    --light-tip-block-border-color: #b0a029;
    --light-tip-block-background-color: #f4f4e6;
    --light-tip-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23b0a029"><path d="M480-80q-33 0-56.5-23.5T400-160h160q0 33-23.5 56.5T480-80ZM320-200v-80h320v80H320Zm10-120q-69-41-109.5-110T180-580q0-125 87.5-212.5T480-880q125 0 212.5 87.5T780-580q0 81-40.5 150T630-320H330Zm24-80h252q45-32 69.5-79T700-580q0-92-64-156t-156-64q-92 0-156 64t-64 156q0 54 24.5 101t69.5 79Zm126 0Z"/></svg>');
    --light-todo-block-border-color: #6faba0;
    --light-todo-block-background-color: #e6f4f3;
    --light-todo-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%236faba0"><path d="M680-80q-83 0-141.5-58.5T480-280q0-83 58.5-141.5T680-480q83 0 141.5 58.5T880-280q0 83-58.5 141.5T680-80Zm67-105 28-28-75-75v-112h-40v128l87 87Zm-547 65q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h167q11-35 43-57.5t70-22.5q40 0 71.5 22.5T594-840h166q33 0 56.5 23.5T840-760v250q-18-13-38-22t-42-16v-212h-80v120H280v-120h-80v560h212q7 22 16 42t22 38H200Zm280-640q17 0 28.5-11.5T520-800q0-17-11.5-28.5T480-840q-17 0-28.5 11.5T440-800q0 17 11.5 28.5T480-760Z"/></svg>');
    --light-warning-block-border-color: #af8141;
    --light-warning-block-background-color: #f4eee6;
    --light-warning-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23af8141"><path d="M109-120q-11 0-20-5.5T75-140q-5-9-5.5-19.5T75-180l370-640q6-10 15.5-15t19.5-5q10 0 19.5 5t15.5 15l370 640q6 10 5.5 20.5T885-140q-5 9-14 14.5t-20 5.5H109Zm69-80h604L480-720 178-200Zm302-40q17 0 28.5-11.5T520-280q0-17-11.5-28.5T480-320q-17 0-28.5 11.5T440-280q0 17 11.5 28.5T480-240Zm0-120q17 0 28.5-11.5T520-400v-120q0-17-11.5-28.5T480-560q-17 0-28.5 11.5T440-520v120q0 17 11.5 28.5T480-360Zm0-100Z"/></svg>');
    --light-theme-icon: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="black"><path d="M480-360q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35Zm0 80q-83 0-141.5-58.5T280-480q0-83 58.5-141.5T480-680q83 0 141.5 58.5T680-480q0 83-58.5 141.5T480-280ZM200-440H40v-80h160v80Zm720 0H760v-80h160v80ZM440-760v-160h80v160h-80Zm0 720v-160h80v160h-80ZM256-650l-101-97 57-59 96 100-52 56Zm492 496-97-101 53-55 101 97-57 59Zm-98-550 97-101 59 57-100 96-56-52ZM154-212l101-97 55 53-97 101-59-57Zm326-268Z"/></svg>');

    --dark-background-color: #202020;
    --dark-deep-background-color: #1a1a1a;
    --dark-text-color: #f0f0f0;
    --dark-border-color: #505050;
    --dark-table-border-color: #777;
    --dark-del-background-color: #67060c;
    --dark-del-color: #ffdcd7;
    --dark-ins-background-color: #033a16;
    --dark-ins-color: #aff5b4;
    --dark-para-color: #5bc0ff;
    --dark-a-color: #5bc0ff;
    --dark-a-visited-color: #c6a8ff;
    --dark-a-hover-color: #afd7ff;
    --dark-mark-color: #ededa8;
    --dark-mark-background-color: #525230;
    --dark-abstract-border-color: #999999;
    --dark-abstract-background-color: #2c2c2c;
    --dark-abstract-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23999999"><path d="M660-160h40v-160h-40v160Zm20-200q8 0 14-6t6-14q0-8-6-14t-14-6q-8 0-14 6t-6 14q0 8 6 14t14 6ZM200-800v640-640 200-200Zm80 400h147q11-23 25.5-43t32.5-37H280v80Zm0 160h123q-3-20-3-40t3-40H280v80ZM200-80q-33 0-56.5-23.5T120-160v-640q0-33 23.5-56.5T200-880h320l240 240v92q-19-6-39-9t-41-3v-40H480v-200H200v640h227q11 23 25.5 43T485-80H200Zm480-400q83 0 141.5 58.5T880-280q0 83-58.5 141.5T680-80q-83 0-141.5-58.5T480-280q0-83 58.5-141.5T680-480Z"/></svg>');
    --dark-blockquote-border-color: #707070;
    --dark-blockquote-background-color: #2c2c2c;
    --dark-blockquote-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="%23707070"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M7.17 17c.51 0 .98-.29 1.2-.74l1.42-2.84c.14-.28.21-.58.21-.89V8c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h2l-1.03 2.06c-.45.89.2 1.94 1.2 1.94zm10 0c.51 0 .98-.29 1.2-.74l1.42-2.84c.14-.28.21-.58.21-.89V8c0-.55-.45-1-1-1h-4c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h2l-1.03 2.06c-.45.89.2 1.94 1.2 1.94z"/></svg>');
    --dark-bug-block-border-color: #ab866f;
    --dark-bug-block-background-color: #373028;
    --dark-bug-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23ab866f"><path d="M480-120q-64 0-114.5-33T283-240l-95 54-40-69 103-60q-3-11-5-22.5t-4-22.5H120v-80h122q2-12 4-23.5t5-22.5l-103-60 40-69 94 55q8-14 18.5-27.5T322-612q-2-7-2-14v-14q0-24 7-46t19-41l-66-66 56-57 70 68q17-9 35.5-13.5T480-800q20 0 39 5t36 14l69-69 56 57-66 66q12 19 18.5 41t6.5 46v13.5q0 6.5-2 13.5 11 11 21.5 25t18.5 28l95-54 40 69-104 59q3 11 5.5 22.5T718-440h122v80H718q-2 12-4 23.5t-5 22.5l103 60-40 69-95-55q-32 54-82.5 87T480-120Zm-76-546q17-7 36.5-10.5T480-680q20 0 38.5 3t35.5 10q-8-23-28-38t-46-15q-26 0-47 15.5T404-666Zm76 466q73 0 116.5-61T640-400q0-70-40.5-135T480-600q-78 0-119 64.5T320-400q0 78 43.5 139T480-200Zm-40-80v-240h80v240h-80Z"/></svg>');
    --dark-details-border-color: #707070;
    --dark-details-background-color: #2c2c2c;
    --dark-details-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23707070"><path d="M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>');
    --dark-decision-block-border-color: #ab6fa2;
    --dark-decision-block-background-color: #30232d;
    --dark-decision-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23ab6fa2"><path d="M160-120v-80h480v80H160Zm226-194L160-540l84-86 228 226-86 86Zm254-254L414-796l86-84 226 226-86 86Zm184 408L302-682l56-56 522 522-56 56Z"/></svg>');
    --dark-del-block-border-color: #be5e64;
    --dark-del-block-background-color: #302323;
    --dark-del-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23be5e64"><path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z"/></svg>');
    --dark-diff-block-border-color: #707070;
    --dark-diff-block-background-color: #2c2c2c;
    --dark-diff-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23707070"><path d="M500-520h80v-80h80v-80h-80v-80h-80v80h-80v80h80v80Zm-80 160h240v-80H420v80ZM320-200q-33 0-56.5-23.5T240-280v-560q0-33 23.5-56.5T320-920h280l240 240v400q0 33-23.5 56.5T760-200H320Zm0-80h440v-360L560-840H320v560ZM160-40q-33 0-56.5-23.5T80-120v-560h80v560h440v80H160Zm160-240v-560 560Z"/></svg>');
    --dark-example-block-border-color: #6f81ab;
    --dark-example-block-background-color: #232630;
    --dark-example-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%236f81ab"><path d="M300-80q-58 0-99-41t-41-99v-520q0-58 41-99t99-41h500v600q-25 0-42.5 17.5T740-220q0 25 17.5 42.5T800-160v80H300Zm-60-267q14-7 29-10t31-3h20v-440h-20q-25 0-42.5 17.5T240-740v393Zm160-13h320v-440H400v440Zm-160 13v-453 453Zm60 187h373q-6-14-9.5-28.5T660-220q0-16 3-31t10-29H300q-26 0-43 17.5T240-220q0 26 17 43t43 17Z"/></svg>');
    --dark-important-block-border-color: #b06262;
    --dark-important-block-background-color: #302323;
    --dark-important-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23b06262"><path d="M480-120q-33 0-56.5-23.5T400-200q0-33 23.5-56.5T480-280q33 0 56.5 23.5T560-200q0 33-23.5 56.5T480-120Zm-80-240v-480h160v480H400Z"/></svg>');
    --dark-ins-block-border-color: #5bab6d;
    --dark-ins-block-background-color: #233023;
    --dark-ins-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%235bab6d"><path d="M440-240h80v-120h120v-80H520v-120h-80v120H320v80h120v120ZM240-80q-33 0-56.5-23.5T160-160v-640q0-33 23.5-56.5T240-880h320l240 240v480q0 33-23.5 56.5T720-80H240Zm280-520v-200H240v640h480v-440H520ZM240-800v200-200 640-640Z"/></svg>');
    --dark-note-block-border-color: #6fab76;
    --dark-note-block-background-color: #233025;
    --dark-note-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%236fab76"><path d="M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>');
    --dark-tip-block-border-color: #a2ab6f;
    --dark-tip-block-background-color: #2f3023;
    --dark-tip-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23a2ab6f"><path d="M480-80q-33 0-56.5-23.5T400-160h160q0 33-23.5 56.5T480-80ZM320-200v-80h320v80H320Zm10-120q-69-41-109.5-110T180-580q0-125 87.5-212.5T480-880q125 0 212.5 87.5T780-580q0 81-40.5 150T630-320H330Zm24-80h252q45-32 69.5-79T700-580q0-92-64-156t-156-64q-92 0-156 64t-64 156q0 54 24.5 101t69.5 79Zm126 0Z"/></svg>');
    --dark-todo-block-border-color: #6fab98;
    --dark-todo-block-background-color: #23302e;
    --dark-todo-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%236fab98"><path d="M680-80q-83 0-141.5-58.5T480-280q0-83 58.5-141.5T680-480q83 0 141.5 58.5T880-280q0 83-58.5 141.5T680-80Zm67-105 28-28-75-75v-112h-40v128l87 87Zm-547 65q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h167q11-35 43-57.5t70-22.5q40 0 71.5 22.5T594-840h166q33 0 56.5 23.5T840-760v250q-18-13-38-22t-42-16v-212h-80v120H280v-120h-80v560h212q7 22 16 42t22 38H200Zm280-640q17 0 28.5-11.5T520-800q0-17-11.5-28.5T480-840q-17 0-28.5 11.5T440-800q0 17 11.5 28.5T480-760Z"/></svg>');
    --dark-warning-block-border-color: #ab9c6f;
    --dark-warning-block-background-color: #302b23;
    --dark-warning-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23ab9c6f"><path d="M109-120q-11 0-20-5.5T75-140q-5-9-5.5-19.5T75-180l370-640q6-10 15.5-15t19.5-5q10 0 19.5 5t15.5 15l370 640q6 10 5.5 20.5T885-140q-5 9-14 14.5t-20 5.5H109Zm69-80h604L480-720 178-200Zm302-40q17 0 28.5-11.5T520-280q0-17-11.5-28.5T480-320q-17 0-28.5 11.5T440-280q0 17 11.5 28.5T480-240Zm0-120q17 0 28.5-11.5T520-400v-120q0-17-11.5-28.5T480-560q-17 0-28.5 11.5T440-520v120q0 17 11.5 28.5T480-360Zm0-100Z"/></svg>');
    --dark-theme-icon: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23f0f0f0"><path d="M480-120q-150 0-255-105T120-480q0-150 105-255t255-105q14 0 27.5 1t26.5 3q-41 29-65.5 75.5T444-660q0 90 63 153t153 63q55 0 101-24.5t75-65.5q2 13 3 26.5t1 27.5q0 150-105 255T480-120Zm0-80q88 0 158-48.5T740-375q-20 5-40 8t-40 3q-123 0-209.5-86.5T364-660q0-20 3-40t8-40q-78 32-126.5 102T200-480q0 116 82 198t198 82Zm-10-270Z"/></svg>');

    --indent: 2.5em;
    --border-radius: 0.25em;
}

/* BEGIN LIGHT AND DARK THEME */

@media (prefers-color-scheme: light) {
    html {
        --background-color: var(--light-background-color);
        --deep-background-color: var(--light-deep-background-color);
        --text-color: var(--light-text-color);
        --border-color: var(--light-border-color);
        --table-border-color: var(--light-table-border-color);
        --del-color: var(--light-del-color);
        --del-background-color: var(--light-del-background-color);
        --ins-color: var(--light-ins-color);
        --ins-background-color: var(--light-ins-background-color);
        --para-color: var(--light-para-color);
        --a-color: var(--light-a-color);
        --a-visited-color: var(--light-a-visited-color);
        --a-hover-color: var(--light-a-hover-color);
        --mark-color: var(--light-mark-color);
        --mark-background-color: var(--light-mark-background-color);
        --abstract-border-color: var(--light-abstract-border-color);
        --abstract-background-color: var(--light-abstract-background-color);
        --abstract-image: var(--light-abstract-image);
        --blockquote-border-color: var(--light-blockquote-border-color);
        --blockquote-background-color: var(--light-blockquote-background-color);
        --blockquote-image: var(--light-blockquote-image);
        --bug-block-border-color: var(--light-bug-block-border-color);
        --bug-block-background-color: var(--light-bug-block-background-color);
        --bug-block-image: var(--light-bug-block-image);
        --decision-block-border-color: var(--light-decision-block-border-color);
        --decision-block-background-color: var(--light-decision-block-background-color);
        --decision-block-image: var(--light-decision-block-image);
        --del-block-border-color: var(--light-del-block-border-color);
        --del-block-background-color: var(--light-del-block-background-color);
        --del-block-image: var(--light-del-block-image);
        --details-border-color: var(--light-details-border-color);
        --details-background-color: var(--light-details-background-color);
        --details-image: var(--light-details-image);
        --diff-block-border-color: var(--light-diff-block-border-color);
        --diff-block-background-color: var(--light-diff-block-background-color);
        --diff-block-image: var(--light-diff-block-image);
        --example-block-border-color: var(--light-example-block-border-color);
        --example-block-background-color: var(--light-example-block-background-color);
        --example-block-image: var(--light-example-block-image);
        --important-block-border-color: var(--light-important-block-border-color);
        --important-block-background-color: var(--light-important-block-background-color);
        --important-block-image: var(--light-important-block-image);
        --ins-block-border-color: var(--light-ins-block-border-color);
        --ins-block-background-color: var(--light-ins-block-background-color);
        --ins-block-image: var(--light-ins-block-image);
        --note-block-border-color: var(--light-note-block-border-color);
        --note-block-background-color: var(--light-note-block-background-color);
        --note-block-image: var(--light-note-block-image);
        --tip-block-border-color: var(--light-tip-block-border-color);
        --tip-block-background-color: var(--light-tip-block-background-color);
        --tip-block-image: var(--light-tip-block-image);
        --todo-block-border-color: var(--light-todo-block-border-color);
        --todo-block-background-color: var(--light-todo-block-background-color);
        --todo-block-image: var(--light-todo-block-image);
        --warning-block-border-color: var(--light-warning-block-border-color);
        --warning-block-background-color: var(--light-warning-block-background-color);
        --warning-block-image: var(--light-warning-block-image);
        --theme-icon: var(--light-theme-icon);
    }
}

@media (prefers-color-scheme: dark) {
    html {
        --background-color: var(--dark-background-color);
        --deep-background-color: var(--dark-deep-background-color);
        --text-color: var(--dark-text-color);
        --border-color: var(--dark-border-color);
        --table-border-color: var(--dark-table-border-color);
        --del-color: var(--dark-del-color);
        --del-background-color: var(--dark-del-background-color);
        --ins-color: var(--dark-ins-color);
        --ins-background-color: var(--dark-ins-background-color);
        --para-color: var(--dark-para-color);
        --a-color: var(--dark-a-color);
        --a-visited-color: var(--dark-a-visited-color);
        --a-hover-color: var(--dark-a-hover-color);
        --mark-color: var(--dark-mark-color);
        --mark-background-color: var(--dark-mark-background-color);
        --abstract-border-color: var(--dark-abstract-border-color);
        --abstract-background-color: var(--dark-abstract-background-color);
        --abstract-image: var(--dark-abstract-image);
        --blockquote-border-color: var(--dark-blockquote-border-color);
        --blockquote-background-color: var(--dark-blockquote-background-color);
        --blockquote-image: var(--dark-blockquote-image);
        --bug-block-border-color: var(--dark-bug-block-border-color);
        --bug-block-background-color: var(--dark-bug-block-background-color);
        --bug-block-image: var(--dark-bug-block-image);
        --decision-block-border-color: var(--dark-decision-block-border-color);
        --decision-block-background-color: var(--dark-decision-block-background-color);
        --decision-block-image: var(--dark-decision-block-image);
        --del-block-border-color: var(--dark-del-block-border-color);
        --del-block-background-color: var(--dark-del-block-background-color);
        --del-block-image: var(--dark-del-block-image);
        --details-border-color: var(--dark-details-border-color);
        --details-background-color: var(--dark-details-background-color);
        --details-image: var(--dark-details-image);
        --diff-block-border-color: var(--dark-diff-block-border-color);
        --diff-block-background-color: var(--dark-diff-block-background-color);
        --diff-block-image: var(--dark-diff-block-image);
        --example-block-border-color: var(--dark-example-block-border-color);
        --example-block-background-color: var(--dark-example-block-background-color);
        --example-block-image: var(--dark-example-block-image);
        --important-block-border-color: var(--dark-important-block-border-color);
        --important-block-background-color: var(--dark-important-block-background-color);
        --important-block-image: var(--dark-important-block-image);
        --ins-block-border-color: var(--dark-ins-block-border-color);
        --ins-block-background-color: var(--dark-ins-block-background-color);
        --ins-block-image: var(--dark-ins-block-image);
        --note-block-border-color: var(--dark-note-block-border-color);
        --note-block-background-color: var(--dark-note-block-background-color);
        --note-block-image: var(--dark-note-block-image);
        --tip-block-border-color: var(--dark-tip-block-border-color);
        --tip-block-background-color: var(--dark-tip-block-background-color);
        --tip-block-image: var(--dark-tip-block-image);
        --todo-block-border-color: var(--dark-todo-block-border-color);
        --todo-block-background-color: var(--dark-todo-block-background-color);
        --todo-block-image: var(--dark-todo-block-image);
        --warning-block-border-color: var(--dark-warning-block-border-color);
        --warning-block-background-color: var(--dark-warning-block-background-color);
        --warning-block-image: var(--dark-warning-block-image);
        --theme-icon: var(--dark-theme-icon);
    }
}

html.light {
    --background-color: var(--light-background-color);
    --deep-background-color: var(--light-deep-background-color);
    --text-color: var(--light-text-color);
    --border-color: var(--light-border-color);
    --table-border-color: var(--light-table-border-color);
    --del-color: var(--light-del-color);
    --del-background-color: var(--light-del-background-color);
    --ins-color: var(--light-ins-color);
    --ins-background-color: var(--light-ins-background-color);
    --para-color: var(--light-para-color);
    --a-color: var(--light-a-color);
    --a-visited-color: var(--light-a-visited-color);
    --a-hover-color: var(--light-a-hover-color);
    --mark-color: var(--light-mark-color);
    --mark-background-color: var(--light-mark-background-color);
    --abstract-border-color: var(--light-abstract-border-color);
    --abstract-background-color: var(--light-abstract-background-color);
    --abstract-image: var(--light-abstract-image);
    --blockquote-border-color: var(--light-blockquote-border-color);
    --blockquote-background-color: var(--light-blockquote-background-color);
    --blockquote-image: var(--light-blockquote-image);
    --bug-block-border-color: var(--light-bug-block-border-color);
    --bug-block-background-color: var(--light-bug-block-background-color);
    --bug-block-image: var(--light-bug-block-image);
    --decision-block-border-color: var(--light-decision-block-border-color);
    --decision-block-background-color: var(--light-decision-block-background-color);
    --decision-block-image: var(--light-decision-block-image);
    --del-block-border-color: var(--light-del-block-border-color);
    --del-block-background-color: var(--light-del-block-background-color);
    --del-block-image: var(--light-del-block-image);
    --details-border-color: var(--light-details-border-color);
    --details-background-color: var(--light-details-background-color);
    --details-image: var(--light-details-image);
    --diff-block-border-color: var(--light-diff-block-border-color);
    --diff-block-background-color: var(--light-diff-block-background-color);
    --diff-block-image: var(--light-diff-block-image);
    --example-block-border-color: var(--light-example-block-border-color);
    --example-block-background-color: var(--light-example-block-background-color);
    --example-block-image: var(--light-example-block-image);
    --important-block-border-color: var(--light-important-block-border-color);
    --important-block-background-color: var(--light-important-block-background-color);
    --important-block-image: var(--light-important-block-image);
    --ins-block-border-color: var(--light-ins-block-border-color);
    --ins-block-background-color: var(--light-ins-block-background-color);
    --ins-block-image: var(--light-ins-block-image);
    --note-block-border-color: var(--light-note-block-border-color);
    --note-block-background-color: var(--light-note-block-background-color);
    --note-block-image: var(--light-note-block-image);
    --tip-block-border-color: var(--light-tip-block-border-color);
    --tip-block-background-color: var(--light-tip-block-background-color);
    --tip-block-image: var(--light-tip-block-image);
    --todo-block-border-color: var(--light-todo-block-border-color);
    --todo-block-background-color: var(--light-todo-block-background-color);
    --todo-block-image: var(--light-todo-block-image);
    --warning-block-border-color: var(--light-warning-block-border-color);
    --warning-block-background-color: var(--light-warning-block-background-color);
    --warning-block-image: var(--light-warning-block-image);
    --theme-icon: var(--light-theme-icon);
}

html.dark {
    --background-color: var(--dark-background-color);
    --deep-background-color: var(--dark-deep-background-color);
    --text-color: var(--dark-text-color);
    --border-color: var(--dark-border-color);
    --table-border-color: var(--dark-table-border-color);
    --del-color: var(--dark-del-color);
    --del-background-color: var(--dark-del-background-color);
    --ins-color: var(--dark-ins-color);
    --ins-background-color: var(--dark-ins-background-color);
    --para-color: var(--dark-para-color);
    --a-color: var(--dark-a-color);
    --a-visited-color: var(--dark-a-visited-color);
    --a-hover-color: var(--dark-a-hover-color);
    --mark-color: var(--dark-mark-color);
    --mark-background-color: var(--dark-mark-background-color);
    --abstract-border-color: var(--dark-abstract-border-color);
    --abstract-background-color: var(--dark-abstract-background-color);
    --abstract-image: var(--dark-abstract-image);
    --blockquote-border-color: var(--dark-blockquote-border-color);
    --blockquote-background-color: var(--dark-blockquote-background-color);
    --blockquote-image: var(--dark-blockquote-image);
    --bug-block-border-color: var(--dark-bug-block-border-color);
    --bug-block-background-color: var(--dark-bug-block-background-color);
    --bug-block-image: var(--dark-bug-block-image);
    --decision-block-border-color: var(--dark-decision-block-border-color);
    --decision-block-background-color: var(--dark-decision-block-background-color);
    --decision-block-image: var(--dark-decision-block-image);
    --del-block-border-color: var(--dark-del-block-border-color);
    --del-block-background-color: var(--dark-del-block-background-color);
    --del-block-image: var(--dark-del-block-image);
    --details-border-color: var(--dark-details-border-color);
    --details-background-color: var(--dark-details-background-color);
    --details-image: var(--dark-details-image);
    --diff-block-border-color: var(--dark-diff-block-border-color);
    --diff-block-background-color: var(--dark-diff-block-background-color);
    --diff-block-image: var(--dark-diff-block-image);
    --example-block-border-color: var(--dark-example-block-border-color);
    --example-block-background-color: var(--dark-example-block-background-color);
    --example-block-image: var(--dark-example-block-image);
    --important-block-border-color: var(--dark-important-block-border-color);
    --important-block-background-color: var(--dark-important-block-background-color);
    --important-block-image: var(--dark-important-block-image);
    --ins-block-border-color: var(--dark-ins-block-border-color);
    --ins-block-background-color: var(--dark-ins-block-background-color);
    --ins-block-image: var(--dark-ins-block-image);
    --note-block-border-color: var(--dark-note-block-border-color);
    --note-block-background-color: var(--dark-note-block-background-color);
    --note-block-image: var(--dark-note-block-image);
    --tip-block-border-color: var(--dark-tip-block-border-color);
    --tip-block-background-color: var(--dark-tip-block-background-color);
    --tip-block-image: var(--dark-tip-block-image);
    --todo-block-border-color: var(--dark-todo-block-border-color);
    --todo-block-background-color: var(--dark-todo-block-background-color);
    --todo-block-image: var(--dark-todo-block-image);
    --warning-block-border-color: var(--dark-warning-block-border-color);
    --warning-block-background-color: var(--dark-warning-block-background-color);
    --warning-block-image: var(--dark-warning-block-image);
    --theme-icon: var(--dark-theme-icon);
}

/* END LIGHT AND DARK THEME */

html {
    margin: 0;
    width: 100%;
    font-family: var(--serif-family);
    font-size: 11pt;

    border-left: var(--border-thickness) solid var(--border-color);
    color: var(--text-color);
    background-color: var(--background-color);
}

body {
    --vertical-margin: 2rem;
    --margin-left: 3rem;
    --margin-right: 2rem;

    margin: var(--vertical-margin) var(--margin-right) var(--vertical-margin) var(--margin-left);
    width: calc(100% - var(--margin-left) - var(--margin-right));
    box-sizing: border-box;
}

main {
    max-width: 60rem;
    margin-left: auto;
    margin-right: auto;
}

p {
    text-align: justify;
}

abstract-block,
blockquote,
bug-block,
code-block,
decision-block,
del-block,
details,
dl,
diff-block,
example-block,
hr,
ol,
important-block,
ins-block,
math[display=block],
note-block,
p,
pre,
tip-block,
todo-block,
ul,
warning-block,
.indent {
    display: block;
    margin-top: 1em;
    margin-bottom: 1em;
}

a {
    color: var(--a-color);
    text-decoration: unset;
}

a:visited {
    color: var(--a-visited-color);
}

a:hover,
a:focus {
    color: var(--a-hover-color);
}

a:hover {
    text-decoration: underline;
}

ol,
ul {
    padding-left: var(--indent);
}

li {
    margin: 0.5em 0;
}

dt {
    margin-top: 0.25em;
    font-style: italic;
    font-weight: bold;
}

dd {
    margin-bottom: 0.25em;
    margin-left: var(--indent);
}

abstract-block,
blockquote,
bug-block,
del-block,
details,
decision-block,
diff-block,
example-block,
important-block,
ins-block,
note-block,
tip-block,
todo-block,
warning-block {
    --border-thickness: 0.25em;
    --padding: 0.5em;

    position: relative;
    width: calc(100% - var(--indent));
    box-sizing: border-box;
    padding: var(--padding);
    margin-left: var(--indent);

    border-top-right-radius: var(--border-radius);
    border-bottom-right-radius: var(--border-radius);
}

abstract-block>:first-child,
blockquote>:first-child,
bug-block>:first-child,
del-block>:first-child,
details>:first-child,
decision-block>:first-child,
diff-block>:first-child,
example-block>:first-child,
important-block>:first-child,
ins-block>:first-child,
note-block>:first-child,
tip-block>:first-child,
todo-block>:first-child,
warning-block>:first-child {
    margin-top: 0;
}

abstract-block>:last-child,
blockquote>:last-child,
bug-block>:last-child,
del-block>:last-child,
details>:last-child,
decision-block>:last-child,
diff-block>:last-child,
example-block>:last-child,
important-block>:last-child,
ins-block>:last-child,
note-block>:last-child,
todo-block>:last-child,
tip-block>:last-child,
warning-block>:last-child {
    margin-bottom: 0;
}

abstract-block::before,
blockquote::before,
bug-block::before,
del-block::before,
details::before,
decision-block::before,
diff-block::before,
example-block::before,
important-block::before,
ins-block::before,
note-block::before,
todo-block::before,
tip-block::before,
warning-block::before {
    position: absolute;
    left: -2.5em;
    top: 0.25em;
    width: 2em;
    height: 2em;

    content: "";
    display: inline-block;
    background-size: contain;
    background-repeat: no-repeat;

}

code,
code-block,
pre,
samp,
tt,
tt-,
.mono {
    font-family: var(--monospace-family);
    font-style: normal;
    font-variant-ligatures: none;
}

code-block:not(.borderless),
pre {
    padding: 0.5em;
    border-radius: var(--border-radius);
    box-sizing: border-box;

    background-color: var(--deep-background-color);
    border: 1px solid var(--border-color);
}

code-block,
pre {
    font-size: 95%;
    width: 100%;
}

code-block,
pre {
    white-space: pre;
    overflow-x: auto;
}

/* INSERTIONS AND DELETIONS */

ins,
ins-lines {
    text-decoration: underline;
    font-weight: 600;
    color: var(--ins-color);
    background-color: var(--ins-background-color);
}

code-block ins,
code-block ins-lines {
    text-decoration: inherit;
}

del {
    text-decoration: line-through;
}

del,
del-lines {
    color: var(--del-color);
    background-color: var(--del-background-color);
}

ins-lines,
del-lines {
    display: inline-block;
    width: 100%;
}

ins h-,
ins-lines h-,
del h-,
del-lines h- {
    color: inherit !important;
    background-color: inherit !important;
}

kbd {
    font-family: var(--sans-serif-family);

    display: inline-block;
    padding: 0 0.25em 0.15em 0.25em;
    border-radius: 0.25em;
    white-space: nowrap;

    background-color: var(--deep-background-color);
    border: 1px solid var(--border-color);
    box-shadow: inset 0 -0.1em 0 var(--border-color);
}

mark {
    color: var(--mark-color);
    background-color: var(--mark-background-color);
}

math:not([display=block]) {
    font-size: 120%;
}

math[display=block] {
    width: fit-content;
    margin-left: var(--indent);

    font-size: 110%;
}

g-term,
f-sans,
f-serif,
wg21-block {
    display: inline;
}

f-sans,
.sans {
    font-family: var(--sans-serif-family);
}

f-serif,
.serif {
    font-family: var(--serif-family);
}

.grammar dd,
g-term {
    font-family: var(--sans-serif-family);
    font-style: oblique;
}

.grammar {
    margin-left: var(--indent);
}

.grammar dt {
    font-weight: normal;
    font-style: normal;
}

.oblique {
    font-style: oblique;
}

.word {
    white-space: nowrap;
}

.wg21-head {
    margin-bottom: 4em;
}

.wg21-head dl {
    font-family: var(--sans-serif-family);
}

.wg21-head dt {
    font-style: normal;
}

/* HEADINGS */

h1,
h2,
h3,
h4,
h5,
h6 {
    position: relative;
    margin: 1rem 0;
}

h1 {
    margin: 2rem 0 1.5rem 0;
    font-size: 250%;
}

h2 {
    margin: 2.5rem 0 1.5rem 0;
    font-size: 166%;
}

h3 {
    margin: 2rem 0 1rem 0;
    font-size: 133%;
}

h4 {
    margin: 1.5rem 0 0.5rem 0;
    font-size: 100%;
}

h5 {
    margin: 1rem 0 0.5rem 0;
    font-size: 100%;
    font-weight: normal;
}

h6 {
    margin: 1rem 0 0.5rem 0;
    font-size: 90%;
    font-weight: normal;
}

table {
    --border: 1px solid var(--table-border-color);

    margin-top: 1em;
    margin-bottom: 1em;
    border-collapse: collapse;
}

table,
tbody,
thead,
th {
    border: var(--border);
}

td {
    border-left: var(--border);
    border-right: var(--border);
}

td,
th {
    padding: 0.1em 0.5em;
}

.para {
    cursor: pointer;
    font-weight: normal;
    font-family: var(--monospace-family);
    text-decoration: none;
    opacity: 0.25;

    position: absolute;
    top: 0.05em;
    left: calc(-1rem - 0.5ch);
}

.para,
.para::before {
    color: var(--para-color);
}

.para:hover,
.para:focus,
:target .para {
    opacity: 1;
}

.para::before {
    content: "§";
}

/* TABLE OF CONTENTS */

.toc {
    --h-indent: 0.75em;

    display: grid;
    grid-template-columns: min-content auto;
}

.toc-num {
    display: inline-block;
    align-self: end;
    padding-right: 3em;

    letter-spacing: 0em;
}

.toc h1,
.toc h2,
.toc h3,
.toc h4,
.toc h5,
.toc h6 {
    display: inline-block;

    font-weight: 500;
    font-size: 12pt;

    margin-top: 0;
    margin-bottom: 0;
}

.toc a,
.toc-num {
    border-bottom: 1px solid rgba(0, 0, 0, 0);
    color: var(--text-color);
}

.toc h1,
.toc-num[data-level="1"] {
    font-size: 125%;
    font-weight: 900;
}

.toc h2,
.toc-num[data-level="2"] {
    font-weight: 700;
}

.toc h3,
.toc-num[data-level="3"] {
    font-weight: 500;
}

.toc h4,
.toc-num[data-level="4"] {
    font-size: 95%;
    font-weight: 400;
}

.toc h5,
.toc-num[data-level="5"] {
    font-size: 90%;
    font-weight: 300;
}

.toc h6,
.toc-num[data-level="6"] {
    font-size: 90%;
    font-weight: 100;
}

.toc a:hover {
    display: inline-block;
    width: 100%;

    color: var(--a-hover-color);
    border-bottom: 1px dashed var(--a-hover-color);
}

.toc h1:not(:nth-child(2)>h1) {
    margin-top: 1.5em;
}

.toc h2:not(:nth-child(2)>h2) {
    margin-top: 0.75em;
}

/** BIBLIOGRAPHY */

.bib {
    display: block;
    margin: 1em 0;
}

.bib-item {
    display: inline-block;
    width: 100%;
    margin: 0.25em 0;
}

.bib-item>* {
    padding: 0 0.125em;
}

.bib-author {
    font-style: italic;
}

.bib-title {
    font-weight: 500;
}

.bib-date {
    font-family: var(--monospace-family);
}

.bib-date::before {
    font-family: var(--serif-family);
    content: "(";
}

.bib-date::after {
    font-family: var(--serif-family);
    content: ")";
}

.bib-link {
    display: block;
    margin-left: var(--indent);

    font-family: var(--sans-serif-family);
    font-style: normal;
}

/* SPECIAL BLOCKS */

intro- {
    display: inline-block;

    font-weight: 600;
    text-transform: uppercase;
    font-family: var(--sans-serif-family);
}

abstract-block {
    background-color: var(--abstract-background-color);
    border-left: var(--border-thickness) solid var(--abstract-border-color);
}

abstract-block::before {
    background-image: var(--abstract-image);
}

abstract-block intro-::before {
    content: "Abstract:";
    color: var(--abstract-border-color);
}

blockquote {
    background-color: var(--blockquote-background-color);
    border-left: var(--border-thickness) solid var(--blockquote-border-color);
}

blockquote::before {
    background-image: var(--blockquote-image);
    top: -0.25em;
}

blockquote intro-::before {
    content: "Quote:";
    color: var(--blockquote-border-color);
}

bug-block {
    background-color: var(--bug-block-background-color);
    border-left: var(--border-thickness) solid var(--bug-block-border-color);
}

bug-block::before {
    background-image: var(--bug-block-image);
}

bug-block intro-::before {
    content: "Bug:";
    color: var(--bug-block-border-color);
}

del-block {
    background-color: var(--del-block-background-color);
    border-left: var(--border-thickness) solid var(--del-block-border-color);
    color: var(--del-color);
}

del-block::before {
    background-image: var(--del-block-image);
}

del-block intro-::before {
    content: "Deleted:";
    color: var(--del-block-border-color);
}

del-block code,
del-block code-block {
    color: var(--text-color);
}

details {
    background-color: var(--details-background-color);
    border-left: var(--border-thickness) solid var(--details-border-color);
}

details::before {
    background-image: var(--details-image);
}

summary {
    font-family: var(--sans-serif-family);
    color: var(--details-border-color);
    user-select: none;
    cursor: pointer;
}

details[open]>summary {
    margin-bottom: 0.5em;
}

decision-block {
    background-color: var(--decision-block-background-color);
    border-left: var(--border-thickness) solid var(--decision-block-border-color);
}

decision-block::before {
    background-image: var(--decision-block-image);
}

decision-block intro-::before {
    content: "Decision:";
    color: var(--decision-block-border-color);
}

diff-block {
    background-color: var(--diff-block-background-color);
    border-left: var(--border-thickness) solid var(--diff-block-border-color);
}

diff-block::before {
    background-image: var(--diff-block-image);
}

diff-block intro-::before {
    content: "Difference:";
    color: var(--diff-block-border-color);
}

example-block {
    background-color: var(--example-block-background-color);
    border-left: var(--border-thickness) solid var(--example-block-border-color);
}

example-block::before {
    background-image: var(--example-block-image);
}

example-block intro-::before {
    content: "Example:";
    color: var(--example-block-border-color);
}

important-block {
    background-color: var(--important-block-background-color);
    border-left: var(--border-thickness) solid var(--important-block-border-color);
}

important-block::before {
    background-image: var(--important-block-image);
}

important-block intro-::before {
    content: "Important:";
    color: var(--important-block-border-color);
}

ins-block {
    background-color: var(--ins-block-background-color);
    border-left: var(--border-thickness) solid var(--ins-block-border-color);
    color: var(--ins-color);
}

ins-block code,
ins-block code-block {
    color: var(--text-color);
}

ins-block::before {
    background-image: var(--ins-block-image);
}

ins-block intro-::before {
    content: "Inserted:";
    color: var(--ins-block-border-color);
}

note-block {
    background-color: var(--note-block-background-color);
    border-left: var(--border-thickness) solid var(--note-block-border-color);
}

note-block::before {
    background-image: var(--note-block-image);
}

note-block intro-::before {
    content: "Note:";
    color: var(--note-block-border-color);
}

tip-block {
    background-color: var(--tip-block-background-color);
    border-left: var(--border-thickness) solid var(--tip-block-border-color);
}

tip-block::before {
    background-image: var(--tip-block-image);
}

tip-block intro-::before {
    content: "Tip:";
    color: var(--tip-block-border-color);
}

todo-block {
    background-color: var(--todo-block-background-color);
    border-left: var(--border-thickness) solid var(--todo-block-border-color);
}

todo-block::before {
    background-image: var(--todo-block-image);
}

todo-block intro-::before {
    content: "Todo:";
    color: var(--todo-block-border-color);
}

warning-block {
    background-color: var(--warning-block-background-color);
    border-left: var(--border-thickness) solid var(--warning-block-border-color);
}

warning-block::before {
    background-image: var(--warning-block-image);
}

warning-block intro-::before {
    content: "Warning:";
    color: var(--warning-block-border-color);
}

.indent {
    margin-left: var(--indent);
}

/* SETTINGS MENU */

#settings:not(.js) {
    display: none;
}

#settings {
    z-index: 999;
    position: fixed;
    display: inline-block;
    top: 1em;
    right: 1em;
}

#theme-icon {
    display: block;
    width: 2.5em;
    height: 2.5em;
    cursor: pointer;
    background-image: var(--theme-icon);
    background-size: contain;
    opacity: 0.25;
}

#theme-icon:hover,
#theme-icon:focus {
    opacity: 1;
}
  </style>
  <style>
@media (prefers-color-scheme: light) {
h-[data-h^=err] { color:#ff0000; }
h-[data-h^=cmt] { color:green; font-style:italic; }
h-[data-h^=cmt_dlim] { font-style:normal; }
h-[data-h^=val] { color:#9f6807; }
h-[data-h^=num] { color:#9f6807; }
h-[data-h^=str] { color:#9f6807; }
h-[data-h^=esc] { color:#9f6807; }
h-[data-h^=null] { color:#00607c; }
h-[data-h^=bool] { color:#9f6807; }
h-[data-h^=this] { color:#00607c; }
h-[data-h^=mac] { color:#6f4e37; }
h-[data-h^=id] { color:#000000; }
h-[data-h^=id_labl] { color:#517a0b; }
h-[data-h^=id_nt] { font-style:italic; }
h-[data-h^=id_nt_dcl] { color:#00607c; font-style:italic; }
h-[data-h^=kw] { color:#00607c; }
h-[data-h^=sym] { color:#570057; }
h-[data-h^=sym_punc] { color:#000000; }
h-[data-h^=sym_par] { color:#af1915; }
h-[data-h^=sym_sqr] { color:#af1915; }
h-[data-h^=sym_brac] { color:#af1915; }
h-[data-h^=diff_head] { color:#777777; }
h-[data-h^=diff_head_hunk] { color:#5c477e; }
h-[data-h^=diff_eq] { color:#000000; }
h-[data-h^=diff_del] { color:#b31d28; background-color:#ffeef0; }
h-[data-h^=diff_ins] { color:#22863a; background-color:#f0fff4; }
h-[data-h^=diff_mod] { color:#7a680d; background-color:#fffdee; }
h-[data-h^=mk_tag] { color:#00607c; }
h-[data-h^=mk_attr] { color:#5c477e; }
h-[data-h^=mk_del] { color:#ce9178; text-decoration:line-through; }
h-[data-h^=mk_ins] { color:#b5cea8; text-decoration:underline; }
h-[data-h^=mk_emph] { font-style:italic; }
h-[data-h^=mk_stro] { font-weight:bold; }
h-[data-h^=mk_emph_stro] { font-style:italic; font-weight:bold; }
h-[data-h^=mk_ulin] { text-decoration:underline; }
h-[data-h^=mk_emph_ulin] { font-style:italic; text-decoration:underline; }
h-[data-h^=mk_stro_ulin] { font-weight:bold; text-decoration:underline; }
h-[data-h^=mk_emph_stro_ulin] { font-weight:bold; font-style:italic; text-decoration:underline; }
h-[data-h^=mk_strk] { text-decoration:line-through; }
h-[data-h^=mk_emph_strk] { font-style:italic; text-decoration:line-through; }
h-[data-h^=mk_stro_strk] { font-weight:bold; text-decoration:line-through; }
h-[data-h^=mk_emph_stro_strk] { font-weight:bold; font-style:italic; text-decoration:line-through; }
h-[data-h^=mk_ulin_strk] { text-decoration:underline line-through; }
h-[data-h^=mk_emph_ulin_strk] { font-style:italic; text-decoration:underline line-through; }
h-[data-h^=mk_stro_ulin_strk] { font-weight:bold; text-decoration:underline line-through; }
h-[data-h^=mk_emph_stro_ulin_strk] { font-weight:bold; font-style:italic; text-decoration:underline line-through; }
h-[data-h^=sh_cmd] { color:#00607c; }
h-[data-h^=sh-opt] { color:#000000; }
h-[data-h^=asm_ins] { color:#00607c; }
h-[data-h^=asm_ins_psu] { color:#9f6807; }
}
@media (prefers-color-scheme: dark) {
h-[data-h^=err] { color:#ff0000; }
h-[data-h^=cmt] { color:#a2e08d; font-style:italic; }
h-[data-h^=cmt_dlim] { font-style:normal; }
h-[data-h^=val] { color:#f2d18d; }
h-[data-h^=num] { color:#f2d18d; }
h-[data-h^=num_dlim] { color:#e6b191; }
h-[data-h^=num_deco] { color:#e6b191; }
h-[data-h^=str] { color:#f2d18d; }
h-[data-h^=str_dlim] { color:#e6b191; }
h-[data-h^=str_deco] { color:#e6b191; }
h-[data-h^=esc] { color:#e6aee6; }
h-[data-h^=null] { color:#62ded6; }
h-[data-h^=bool] { color:#f2d18d; }
h-[data-h^=this] { color:#62ded6; }
h-[data-h^=mac] { color:#cc946e; }
h-[data-h^=id] { color:#f0f0f0; }
h-[data-h^=id_labl] { color:#d8eda6; }
h-[data-h^=id_nt] { font-style:italic; }
h-[data-h^=id_nt_dcl] { color:#62ded6; font-style:italic; }
h-[data-h^=kw] { color:#62ded6; }
h-[data-h^=sym] { color:#baa6b9; }
h-[data-h^=sym_punc] { color:#d0d0d0; }
h-[data-h^=sym_par] { color:#fa7878; }
h-[data-h^=sym_sqr] { color:#fa7878; }
h-[data-h^=sym_brac] { color:#fa7878; }
h-[data-h^=diff_head] { color:#777777; }
h-[data-h^=diff_head_hunk] { color:#edc385; }
h-[data-h^=diff_eq] { color:#e7e7e7; }
h-[data-h^=diff_del] { color:#ffdcd7; background-color:#67060c; }
h-[data-h^=diff_ins] { color:#aff5b4; background-color:#033a16; }
h-[data-h^=diff_mod] { color:#fff4d7; background-color:#674d06; }
h-[data-h^=mk_tag] { color:#62ded6; }
h-[data-h^=mk_attr] { color:#a4c4de; }
h-[data-h^=mk_del] { color:#ce9178; text-decoration:line-through; }
h-[data-h^=mk_ins] { color:#b5cea8; text-decoration:underline; }
h-[data-h^=mk_emph] { font-style:italic; }
h-[data-h^=mk_stro] { font-weight:bold; }
h-[data-h^=mk_emph_stro] { font-style:italic; font-weight:bold; }
h-[data-h^=mk_ulin] { text-decoration:underline; }
h-[data-h^=mk_emph_ulin] { font-style:italic; text-decoration:underline; }
h-[data-h^=mk_stro_ulin] { font-weight:bold; text-decoration:underline; }
h-[data-h^=mk_emph_stro_ulin] { font-weight:bold; font-style:italic; text-decoration:underline; }
h-[data-h^=mk_strk] { text-decoration:line-through; }
h-[data-h^=mk_emph_strk] { font-style:italic; text-decoration:line-through; }
h-[data-h^=mk_stro_strk] { font-weight:bold; text-decoration:line-through; }
h-[data-h^=mk_emph_stro_strk] { font-weight:bold; font-style:italic; text-decoration:line-through; }
h-[data-h^=mk_ulin_strk] { text-decoration:underline line-through; }
h-[data-h^=mk_emph_ulin_strk] { font-style:italic; text-decoration:underline line-through; }
h-[data-h^=mk_stro_ulin_strk] { font-weight:bold; text-decoration:underline line-through; }
h-[data-h^=mk_emph_stro_ulin_strk] { font-weight:bold; font-style:italic; text-decoration:underline line-through; }
h-[data-h^=sh_cmd] { color:#62ded6; }
h-[data-h^=sh-opt] { color:#f0f0f0; }
h-[data-h^=asm_ins] { color:#62ded6; }
h-[data-h^=asm_ins_psu] { color:#e6aee6; }
}

html.light h-[data-h^=err] { color:#ff0000; }
html.light h-[data-h^=cmt] { color:green; font-style:italic; }
html.light h-[data-h^=cmt_dlim] { font-style:normal; }
html.light h-[data-h^=val] { color:#9f6807; }
html.light h-[data-h^=num] { color:#9f6807; }
html.light h-[data-h^=str] { color:#9f6807; }
html.light h-[data-h^=esc] { color:#9f6807; }
html.light h-[data-h^=null] { color:#00607c; }
html.light h-[data-h^=bool] { color:#9f6807; }
html.light h-[data-h^=this] { color:#00607c; }
html.light h-[data-h^=mac] { color:#6f4e37; }
html.light h-[data-h^=id] { color:#000000; }
html.light h-[data-h^=id_labl] { color:#517a0b; }
html.light h-[data-h^=id_nt] { font-style:italic; }
html.light h-[data-h^=id_nt_dcl] { color:#00607c; font-style:italic; }
html.light h-[data-h^=kw] { color:#00607c; }
html.light h-[data-h^=sym] { color:#570057; }
html.light h-[data-h^=sym_punc] { color:#000000; }
html.light h-[data-h^=sym_par] { color:#af1915; }
html.light h-[data-h^=sym_sqr] { color:#af1915; }
html.light h-[data-h^=sym_brac] { color:#af1915; }
html.light h-[data-h^=diff_head] { color:#777777; }
html.light h-[data-h^=diff_head_hunk] { color:#5c477e; }
html.light h-[data-h^=diff_eq] { color:#000000; }
html.light h-[data-h^=diff_del] { color:#b31d28; background-color:#ffeef0; }
html.light h-[data-h^=diff_ins] { color:#22863a; background-color:#f0fff4; }
html.light h-[data-h^=diff_mod] { color:#7a680d; background-color:#fffdee; }
html.light h-[data-h^=mk_tag] { color:#00607c; }
html.light h-[data-h^=mk_attr] { color:#5c477e; }
html.light h-[data-h^=mk_del] { color:#ce9178; text-decoration:line-through; }
html.light h-[data-h^=mk_ins] { color:#b5cea8; text-decoration:underline; }
html.light h-[data-h^=mk_emph] { font-style:italic; }
html.light h-[data-h^=mk_stro] { font-weight:bold; }
html.light h-[data-h^=mk_emph_stro] { font-style:italic; font-weight:bold; }
html.light h-[data-h^=mk_ulin] { text-decoration:underline; }
html.light h-[data-h^=mk_emph_ulin] { font-style:italic; text-decoration:underline; }
html.light h-[data-h^=mk_stro_ulin] { font-weight:bold; text-decoration:underline; }
html.light h-[data-h^=mk_emph_stro_ulin] { font-weight:bold; font-style:italic; text-decoration:underline; }
html.light h-[data-h^=mk_strk] { text-decoration:line-through; }
html.light h-[data-h^=mk_emph_strk] { font-style:italic; text-decoration:line-through; }
html.light h-[data-h^=mk_stro_strk] { font-weight:bold; text-decoration:line-through; }
html.light h-[data-h^=mk_emph_stro_strk] { font-weight:bold; font-style:italic; text-decoration:line-through; }
html.light h-[data-h^=mk_ulin_strk] { text-decoration:underline line-through; }
html.light h-[data-h^=mk_emph_ulin_strk] { font-style:italic; text-decoration:underline line-through; }
html.light h-[data-h^=mk_stro_ulin_strk] { font-weight:bold; text-decoration:underline line-through; }
html.light h-[data-h^=mk_emph_stro_ulin_strk] { font-weight:bold; font-style:italic; text-decoration:underline line-through; }
html.light h-[data-h^=sh_cmd] { color:#00607c; }
html.light h-[data-h^=sh-opt] { color:#000000; }
html.light h-[data-h^=asm_ins] { color:#00607c; }
html.light h-[data-h^=asm_ins_psu] { color:#9f6807; }

html.dark h-[data-h^=err] { color:#ff0000; }
html.dark h-[data-h^=cmt] { color:#a2e08d; font-style:italic; }
html.dark h-[data-h^=cmt_dlim] { font-style:normal; }
html.dark h-[data-h^=val] { color:#f2d18d; }
html.dark h-[data-h^=num] { color:#f2d18d; }
html.dark h-[data-h^=num_dlim] { color:#e6b191; }
html.dark h-[data-h^=num_deco] { color:#e6b191; }
html.dark h-[data-h^=str] { color:#f2d18d; }
html.dark h-[data-h^=str_dlim] { color:#e6b191; }
html.dark h-[data-h^=str_deco] { color:#e6b191; }
html.dark h-[data-h^=esc] { color:#e6aee6; }
html.dark h-[data-h^=null] { color:#62ded6; }
html.dark h-[data-h^=bool] { color:#f2d18d; }
html.dark h-[data-h^=this] { color:#62ded6; }
html.dark h-[data-h^=mac] { color:#cc946e; }
html.dark h-[data-h^=id] { color:#f0f0f0; }
html.dark h-[data-h^=id_labl] { color:#d8eda6; }
html.dark h-[data-h^=id_nt] { font-style:italic; }
html.dark h-[data-h^=id_nt_dcl] { color:#62ded6; font-style:italic; }
html.dark h-[data-h^=kw] { color:#62ded6; }
html.dark h-[data-h^=sym] { color:#baa6b9; }
html.dark h-[data-h^=sym_punc] { color:#d0d0d0; }
html.dark h-[data-h^=sym_par] { color:#fa7878; }
html.dark h-[data-h^=sym_sqr] { color:#fa7878; }
html.dark h-[data-h^=sym_brac] { color:#fa7878; }
html.dark h-[data-h^=diff_head] { color:#777777; }
html.dark h-[data-h^=diff_head_hunk] { color:#edc385; }
html.dark h-[data-h^=diff_eq] { color:#e7e7e7; }
html.dark h-[data-h^=diff_del] { color:#ffdcd7; background-color:#67060c; }
html.dark h-[data-h^=diff_ins] { color:#aff5b4; background-color:#033a16; }
html.dark h-[data-h^=diff_mod] { color:#fff4d7; background-color:#674d06; }
html.dark h-[data-h^=mk_tag] { color:#62ded6; }
html.dark h-[data-h^=mk_attr] { color:#a4c4de; }
html.dark h-[data-h^=mk_del] { color:#ce9178; text-decoration:line-through; }
html.dark h-[data-h^=mk_ins] { color:#b5cea8; text-decoration:underline; }
html.dark h-[data-h^=mk_emph] { font-style:italic; }
html.dark h-[data-h^=mk_stro] { font-weight:bold; }
html.dark h-[data-h^=mk_emph_stro] { font-style:italic; font-weight:bold; }
html.dark h-[data-h^=mk_ulin] { text-decoration:underline; }
html.dark h-[data-h^=mk_emph_ulin] { font-style:italic; text-decoration:underline; }
html.dark h-[data-h^=mk_stro_ulin] { font-weight:bold; text-decoration:underline; }
html.dark h-[data-h^=mk_emph_stro_ulin] { font-weight:bold; font-style:italic; text-decoration:underline; }
html.dark h-[data-h^=mk_strk] { text-decoration:line-through; }
html.dark h-[data-h^=mk_emph_strk] { font-style:italic; text-decoration:line-through; }
html.dark h-[data-h^=mk_stro_strk] { font-weight:bold; text-decoration:line-through; }
html.dark h-[data-h^=mk_emph_stro_strk] { font-weight:bold; font-style:italic; text-decoration:line-through; }
html.dark h-[data-h^=mk_ulin_strk] { text-decoration:underline line-through; }
html.dark h-[data-h^=mk_emph_ulin_strk] { font-style:italic; text-decoration:underline line-through; }
html.dark h-[data-h^=mk_stro_ulin_strk] { font-weight:bold; text-decoration:underline line-through; }
html.dark h-[data-h^=mk_emph_stro_ulin_strk] { font-weight:bold; font-style:italic; text-decoration:underline line-through; }
html.dark h-[data-h^=sh_cmd] { color:#62ded6; }
html.dark h-[data-h^=sh-opt] { color:#f0f0f0; }
html.dark h-[data-h^=asm_ins] { color:#62ded6; }
html.dark h-[data-h^=asm_ins_psu] { color:#e6aee6; }
  </style>
  <script>
const theme = localStorage.getItem("cowel-theme");
if (theme !== null) {
    document.documentElement.className = theme;
}
  </script>
<title>Deprecate implicit conversions
          between char8_t, char16_t, and char32_t</title></head>
<body>
<div id=settings tabindex=0>
    <div id=theme-icon></div>
    <script>
        const settings = document.getElementById("settings");
        const htmlClasses = document.documentElement.classList;
        const themeIcon = document.getElementById("theme-icon");

        settings.classList.add("js");
        themeIcon.onclick = () => {
            const prefersDark = window.matchMedia("(prefers-color-scheme: dark)");
            const overrideClass = prefersDark.matches ? "light" : "dark";
            if (htmlClasses.contains("light")) {
                htmlClasses.remove("light");
                localStorage.removeItem("cowel-theme");
            } else if (htmlClasses.contains("dark")) {
                htmlClasses.remove("dark");
                localStorage.removeItem("cowel-theme");
            } else {
                htmlClasses.add(overrideClass);
                // to avoid legal issues or controversy in general,
                // we don't mess with local storage when the page is hosted in arbitrary places
                if (window.location.protocol === "file:") {
                    localStorage.setItem("cowel-theme", overrideClass);
                }
            }
        };
        settings.onkeydown = (e) => {
            if (e.key === "Enter" || e.key === " ") {
                event.preventDefault();
                themeIcon.onclick();
            }
        };
    </script>
</div>
<main>
<style>
  ins-block .para::before {
    display: none;
  }

  .grammar dd {
    margin-top: 0;
    margin-bottom: 0;
  }

  .opt {
    font-family: var(--serif-family);
  }

  .stable-ref {
    float: right;
  }

  .five-way-poll {
    table-layout: fixed;
  }
  .five-way-poll td {
    width: 20%;
    text-align: center;
  }

  q::before {
    content: "“";
  }
  q::after {
    content: "”";
  }
</style>

<div class=wg21-head><h1>Deprecate implicit conversions
          between <tt->char8_t</tt->, <tt->char16_t</tt->, and <tt->char32_t</tt-></h1>

<dl>
  <dt>Document number:</dt> <dd><a href=https://wg21.link/P3695R1>P3695R1</a></dd>
  <dt>Date:</dt>            <dd><tt->2025-09-09</tt-></dd>
  <dt>Audience:</dt>        <dd>EWG, SG16</dd>
  <dt>Project:</dt>         <dd>ISO/IEC 14882 Programming Languages — C++, ISO/IEC JTC1/SC22/WG21</dd>
  <dt>Author:</dt>          <dd>Jan Schultke &lt;<a href=mailto:janschultke@gmail.com class=sans>janschultke@gmail.com</a>&gt;</dd>
  <dt>GitHub Issue:</dt>    <dd><a href=https://wg21.link/P3695/github class=sans>wg21.link/P3695/github</a></dd>
  <dt>Source:</dt>          <dd><a href=https://github.com/Eisenwave/cpp-proposals/blob/master/src/deprecate-unicode-conversion.cow class=sans>github.com/Eisenwave/cpp-proposals/blob/master/src/deprecate-unicode-conversion.cow</a></dd>
</dl>
<hr/>
</div>

<abstract-block><p><intro-></intro-> 
Implicit conversions between <code><h- data-h=kw_type>char8_t</h-></code> and <code><h- data-h=kw_type>char16_t</h-></code> or and <code><h- data-h=kw_type>char32_t</h-></code>
are bug-prone and thus harmful to the language.
I propose to deprecate them.
</p></abstract-block>

<h2 id=contents><a class=para href=#contents></a>Contents</h2>

<div class=toc><div class=toc-num data-level=2>1</div>
<a href=#revision-history><h2>Revision history</h2></a>
<div class=toc-num data-level=3>1.1</div>
<a href=#changes-since-r0><h3>Changes since R0</h3></a>
<div class=toc-num data-level=2>2</div>
<a href=#introduction><h2>Introduction</h2></a>
<div class=toc-num data-level=3>2.1</div>
<a href=#its-not-hypothetical%2e-this-really-happens%2e><h3>It's not hypothetical. This really happens.</h3></a>
<div class=toc-num data-level=3>2.2</div>
<a href=#the-underlying-problem><h3>The underlying problem</h3></a>
<div class=toc-num data-level=2>3</div>
<a href=#scope><h2>Scope</h2></a>
<div class=toc-num data-level=3>3.1</div>
<a href=#safe-comparisons><h3>What about "safe" comparisons?</h3></a>
<div class=toc-num data-level=3>3.2</div>
<a href=#char16_t-char32_t><h3>What about <code><h- data-h=kw_type>char16_t</h-></code> and <code><h- data-h=kw_type>char32_t</h-></code>?</h3></a>
<div class=toc-num data-level=3>3.3</div>
<a href=#char-and-wchar_t><h3>What about <code><h- data-h=kw_type>char</h-></code> and <code><h- data-h=kw_type>wchar_t</h-></code>?</h3></a>
<div class=toc-num data-level=3>3.4</div>
<a href=#integer-comparisons><h3>What about conversions with integers?</h3></a>
<div class=toc-num data-level=3>3.5</div>
<a href=#after-deprecation><h3>What comes after deprecation?</h3></a>
<div class=toc-num data-level=2>4</div>
<a href=#impact-on-existing-code><h2>Impact on existing code</h2></a>
<div class=toc-num data-level=3>4.1</div>
<a href=#replacement><h3>Replacement for deprecated behavior</h3></a>
<div class=toc-num data-level=2>5</div>
<a href=#implementation-experience><h2>Implementation experience</h2></a>
<div class=toc-num data-level=2>6</div>
<a href=#wording><h2>Wording</h2></a>
<div class=toc-num data-level=2>7</div>
<a href=#references><h2>References</h2></a>
</div>

<h2 id=revision-history><a class=para href=#revision-history></a>1. Revision history</h2>

<h3 id=changes-since-r0><a class=para href=#changes-since-r0></a>1.1. Changes since R0</h3>

<ul>
  <li>
    limited deprecation to conversions involving <code><h- data-h=kw_type>char8_t</h-></code>;
    see <a href=#char16_t-char32_t>§3.2. What about <code><h- data-h=kw_type>char16_t</h-></code> and <code><h- data-h=kw_type>char32_t</h-></code>?</a>
  </li>
  <li>rebased <a href=#wording>§6. Wording</a> on <a href="https://wg21%2elink/n5014">[N5014]</a></li>
</ul>

<h2 id=introduction><a class=para href=#introduction></a>2. Introduction</h2>

<p>Implicit conversions between <code><h- data-h=kw_type>char8_t</h-></code> and <code><h- data-h=kw_type>char32_t</h-></code> invite bugs:
</p>
<bug-block><p><intro-></intro-> 
Until <em>very</em> recently, no major compiler would detect the following "bad comparison":
</p><code-block><h- data-h=kw>constexpr</h-> <h- data-h=kw_type>bool</h-> <h- data-h=id>contains_oe</h-><h- data-h=sym_par>(</h-><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>u8string_view</h-> <h- data-h=id>str</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>for</h-> <h- data-h=sym_par>(</h-><h- data-h=kw_type>char8_t</h-> <h- data-h=id>c</h-> <h- data-h=sym_punc>:</h-> <h- data-h=id>str</h-><h- data-h=sym_par>)</h->
        <h- data-h=kw_ctrl>if</h-> <h- data-h=sym_par>(</h-><h- data-h=id>c</h-> <h- data-h=sym_op>==</h-> <h- data-h=str_deco>U</h-><h- data-h=str_dlim>'</h-><h- data-h=str>ö</h-><h- data-h=str_dlim>'</h-><h- data-h=sym_par>)</h->
            <h- data-h=kw_ctrl>return</h-> <h- data-h=bool>true</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=bool>false</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->
<h- data-h=kw>static_assert</h-><h- data-h=sym_par>(</h-><h- data-h=id>contains_oe</h-><h- data-h=sym_par>(</h-><h- data-h=str_deco>u8</h-><h- data-h=str_dlim>"</h-><h- data-h=str>ö</h-><h- data-h=str_dlim>"</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> fails?!</h-></code-block>
<p><code><h- data-h=id>c</h-> <h- data-h=sym_op>==</h-> <h- data-h=str_deco>U</h-><h- data-h=str_dlim>'</h-><h- data-h=str>ö</h-><h- data-h=str_dlim>'</h-></code> always fails if <code><h- data-h=id>c</h-></code> is a UTF-8 code unit
because it is equivalent to <code><h- data-h=id>c</h-> <h- data-h=sym_op>==</h-> <h- data-h=kw_type>char32_t</h-><h- data-h=sym_par>(</h-><h- data-h=num_deco>0x</h-><h- data-h=num>f6</h-><h- data-h=sym_par>)</h-></code>,
and a UTF-8 code unit cannot have this value.
</p></bug-block>

<bug-block><p><intro-></intro-> 
An even more evil variation is a search which yields false positives:
</p><code-block><h- data-h=kw>constexpr</h-> <h- data-h=kw_type>bool</h-> <h- data-h=id>contains_nbsp</h-><h- data-h=sym_par>(</h-><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>u8string_view</h-> <h- data-h=id>str</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>for</h-> <h- data-h=sym_par>(</h-><h- data-h=kw_type>char8_t</h-> <h- data-h=id>c</h-> <h- data-h=sym_punc>:</h-> <h- data-h=id>str</h-><h- data-h=sym_par>)</h->
        <h- data-h=kw_ctrl>if</h-> <h- data-h=sym_par>(</h-><h- data-h=id>c</h-> <h- data-h=sym_op>==</h-> <h- data-h=str_deco>U</h-><h- data-h=str_dlim>'</h-><h- data-h=esc>\</h-><h- data-h=esc>N{NO-BREAK SPACE}</h-><h- data-h=str_dlim>'</h-><h- data-h=sym_par>)</h->
            <h- data-h=kw_ctrl>return</h-> <h- data-h=bool>true</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=bool>false</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->
<h- data-h=kw>static_assert</h-><h- data-h=sym_par>(</h-><h- data-h=id>contains_nbsp</h-><h- data-h=sym_par>(</h-><h- data-h=str_deco>u8</h-><h- data-h=str_dlim>"</h-><h- data-h=esc>\</h-><h- data-h=esc>N{CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK}</h-><h- data-h=str_dlim>"</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> OK?!</h-></code-block>
<p>The assertion succeeds because Ԡ (U+0520) is UTF-8 encoded as <code><h- data-h=num_deco>0x</h-><h- data-h=num>d4</h-></code>, <code><h- data-h=num_deco>0x</h-><h- data-h=num>a0</h-></code>,
and NBSP is U+00A0,
so the <code><h- data-h=kw_type>char32_t</h-><h- data-h=sym_par>(</h-><h- data-h=num_deco>0x</h-><h- data-h=num>a0</h-><h- data-h=sym_par>)</h-></code> value matches the second UTF-8 code unit of U+0520.
</p></bug-block>

<bug-block><p><intro-></intro-> 
Such bad comparisons often don't occur directly, but within <code><h- data-h=str>&lt;algorithm&gt;</h-></code>:
</p><code-block><h- data-h=kw>constexpr</h-> <h- data-h=kw_type>bool</h-> <h- data-h=id>is_umlaut</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>char32_t</h-> <h- data-h=id>c</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>c</h-> <h- data-h=sym_op>==</h-> <h- data-h=str_deco>U</h-><h- data-h=str_dlim>'</h-><h- data-h=str>ä</h-><h- data-h=str_dlim>'</h-> <h- data-h=sym_op>||</h-> <h- data-h=id>c</h-> <h- data-h=sym_op>==</h-> <h- data-h=str_deco>U</h-><h- data-h=str_dlim>'</h-><h- data-h=str>ö</h-><h- data-h=str_dlim>'</h-> <h- data-h=sym_op>||</h-> <h- data-h=id>c</h-> <h- data-h=sym_op>==</h-> <h- data-h=str_deco>U</h-><h- data-h=str_dlim>'</h-><h- data-h=str>ü</h-><h- data-h=str_dlim>'</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> ...</h->
<h- data-h=kw>constexpr</h-> <h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>u8string_view</h-> <h- data-h=id>umlauts</h-> <h- data-h=sym_op>=</h-> <h- data-h=str_deco>u8</h-><h- data-h=str_dlim>"</h-><h- data-h=str>äöü</h-><h- data-h=str_dlim>"</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw>static_assert</h-><h- data-h=sym_par>(</h-><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>ranges</h-><h- data-h=sym_op>::</h-><h- data-h=id>find_if</h-><h- data-h=sym_par>(</h-><h- data-h=id>umlauts</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>is_umlaut</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>!=</h-> <h- data-h=id>umlauts</h-><h- data-h=sym_op>.</h-><h- data-h=id>end</h-><h- data-h=sym_par>(</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> fails?!</h-></code-block>
<p>Note that the "bad comparison" occurs between two <code><h- data-h=kw_type>char32_t</h-></code> in <code><h- data-h=id>is_umlaut</h-></code>,
which demonstrates that implicit conversions in general are bug-prone, not just comparisons.
We obviously don't want to deprecate <code><h- data-h=kw_type>char32_t</h-> <h- data-h=sym_op>==</h-> <h- data-h=kw_type>char32_t</h-></code>.
</p></bug-block>

<p>Conversions "the other way" (e.g. <code><h- data-h=kw_type>char32_t</h-></code> → <code><h- data-h=kw_type>char8_t</h-></code>)
are obviously bug-prone too because information is lost,
but such bugs can already be caught by all major compilers' warnings,
and they are problematic for the same reason as <code><h- data-h=kw_type>int</h-></code> → <code><h- data-h=kw_type>short</h-></code>,
not because of anything specific to character types.
The listed bugs are interesting <em>precisely because</em> no information is lost.
</p>
<h3 id=its-not-hypothetical.-this-really-happens.><a class=para href=#its-not-hypothetical%2e-this-really-happens%2e></a>2.1. It's not hypothetical. This really happens.</h3>

<p>These kinds of bugs are not far-fetched hypotheticals either;
I have written such bugs myself,
and have had them contributed
to my syntax highlighter <a href="https://github%2ecom/Eisenwave/ulight">[µlight]</a>,
which makes extensive use of <code><h- data-h=kw_type>char8_t</h-></code> and <code><h- data-h=kw_type>char32_t</h-></code>.
Very early in development, I have realized how dangerous these implicit conversions are,
so most functions in the style of <code><h- data-h=id>is_umlaut</h-></code> have a deleted overload:
</p><code-block><h- data-h=kw>constexpr</h-> <h- data-h=kw_type>bool</h-> <h- data-h=id>is_umlaut</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>char8_t</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>=</h-> <h- data-h=kw>delete</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw>constexpr</h-> <h- data-h=kw_type>bool</h-> <h- data-h=id>is_umlaut</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>char32_t</h-> <h- data-h=id>c</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>c</h-> <h- data-h=sym_op>==</h-> <h- data-h=str_deco>U</h-><h- data-h=str_dlim>'</h-><h- data-h=str>ä</h-><h- data-h=str_dlim>'</h-> <h- data-h=sym_op>||</h-> <h- data-h=id>c</h-> <h- data-h=sym_op>==</h-> <h- data-h=str_deco>U</h-><h- data-h=str_dlim>'</h-><h- data-h=str>ö</h-><h- data-h=str_dlim>'</h-> <h- data-h=sym_op>||</h-> <h- data-h=id>c</h-> <h- data-h=sym_op>==</h-> <h- data-h=str_deco>U</h-><h- data-h=str_dlim>'</h-><h- data-h=str>ü</h-><h- data-h=str_dlim>'</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-></code-block>

<note-block><p><intro-></intro-> 
Compilers do have warnings which detect comparisons which are always <code><h- data-h=bool>false</h-></code>,
but technically, <code><h- data-h=kw_type>char8_t</h-></code> can have the values <code><h- data-h=num_deco>0x</h-><h- data-h=num>f6</h-></code> and <code><h- data-h=num_deco>0x</h-><h- data-h=num>a0</h-></code>,
so it is undetectable.
</p></note-block>

<h3 id=the-underlying-problem><a class=para href=#the-underlying-problem></a>2.2. The underlying problem</h3>

<p>The underlying problem is that <code><h- data-h=kw_type>char8_t</h-> <h- data-h=sym_op>==</h-> <h- data-h=kw_type>char32_t</h-></code> is <code><h- data-h=id>Car</h-> <h- data-h=sym_op>==</h-> <h- data-h=id>Banana</h-></code>.
In general, it is meaningless to compare code units with different encodings.
</p>
<p>To be fair, Unicode character types aren't strictly required to store Unicode code units.
However, that is their primary purpose, and the assumption holds true for any Unicode
<g-term>character-literal</g-term> and <g-term>string-literal</g-term>.
</p>
<h2 id=scope><a class=para href=#scope></a>3. Scope</h2>

<p>I propose to deprecate implicit conversions between
<code><h- data-h=kw_type>char8_t</h-></code> and <code><h- data-h=kw_type>char16_t</h-></code> or <code><h- data-h=kw_type>char32_t</h-></code>.
As demonstrated above, these are extremely bug-prone.
Conversions between <code><h- data-h=kw_type>char16_t</h-></code> and <code><h- data-h=kw_type>char32_t</h-></code> are not affected.
</p>
<h3 id=safe-comparisons><a class=para href=#safe-comparisons></a>3.1. What about "safe" comparisons?</h3>

<p>In comparisons between code units,
certain ranges of code points yield the expected result.
For example, <code><h- data-h=str_deco>u8</h-><h- data-h=str_dlim>'</h-><h- data-h=str>x</h-><h- data-h=str_dlim>'</h-> <h- data-h=sym_op>==</h-> <h- data-h=str_deco>U</h-><h- data-h=str_dlim>'</h-><h- data-h=str>x</h-><h- data-h=str_dlim>'</h-></code> is <code><h- data-h=bool>true</h-></code>
because all Unicode encodings are ASCII-compatible,
so the numeric value of anything in the basic latin block (≤ U+007F)
will have the same single-code-unit value in UTF-8, UTF-16, and UTF-32.
</p>
<p>However, even those should be deprecated because:
</p><ul>
  <li>
    Keeping these valid would essentially leak implementation details of Unicode encodings
    into the C++ core language,
    which seems like unclean design.
  </li>
  <li>
    To rely on this "feature", the developer needs to memorize which code points are "safe to use".
    It is not obvious whether <code><h- data-h=id>c</h-> <h- data-h=sym_op>==</h-> <h- data-h=str_deco>U</h-><h- data-h=str_dlim>'</h-><h- data-h=str>€</h-><h- data-h=str_dlim>'</h-></code> or <code><h- data-h=id>c</h-> <h- data-h=sym_op>==</h-> <h- data-h=str_deco>U</h-><h- data-h=str_dlim>'</h-><h- data-h=str>$</h-><h- data-h=str_dlim>'</h-></code> are always safe
    (hint: the latter one is),
    and it's quite likely that someone uses this "feature" accidentally.
  </li>
  <li>
    It would make this "feature" (or lack thereof) harder to teach than it needs to be.
    The rule can be very simple: different <code><h- data-h=id_type>charN_t</h-></code> cannot be converted to one another.
    Simple rules are easy to teach.
  </li>
</ul>

<h3 id=char16_t-char32_t><a class=para href=#char16_t-char32_t></a>3.2. What about <code><h- data-h=kw_type>char16_t</h-></code> and <code><h- data-h=kw_type>char32_t</h-></code>?</h3>

<p>Following some negative feedback on <a href="https://github%2ecom/llvm/llvm-project/pull/138708">[ClangWarning]</a>,
the proposal no longer seeks to deprecate conversions between <code><h- data-h=kw_type>char16_t</h-></code> and <code><h- data-h=kw_type>char32_t</h-></code>.
While these are not guaranteed to be meaningful,
crucially,
both UTF-16 and UTF-32 encodings consist of code points, not code units.
</p>
<p>The difference is that UTF-16 may also include "surrogate code points"
which may be combined with a subsequent code point.
Surrogate code points do not exist in UTF-32.
Consequently, comparing correct UTF-16 to UTF-32 does not yield false positives.
It is impossible for correctly encoded <code><h- data-h=kw_type>char32_t</h-></code> to compare equal to <code><h- data-h=kw_type>char16_t</h-></code>
unless they represent the same code point.
However, it is possible to have false negatives
when searching for a UTF-32 code point in UTF-16 text,
considering that some code points need to be encoded using surrogates.
</p>
<p>It also also much less likely that <code><h- data-h=kw_type>char16_t</h-></code> and <code><h- data-h=kw_type>char32_t</h-></code> actually manifest as a bug.
An application that only uses, say, Basic Latin characters and German or Norwegian
umlauts can use <code><h- data-h=kw_type>char16_t</h-></code> and <code><h- data-h=kw_type>char32_t</h-></code> interchangeably.
By contrast, mixing <code><h- data-h=kw_type>char8_t</h-></code> with other Unicode character types will almost
certainly blow up in the user's face if the application processes any kind of non-ASCII text.
</p>
<h3 id=char-and-wchar_t><a class=para href=#char-and-wchar_t></a>3.3. What about <code><h- data-h=kw_type>char</h-></code> and <code><h- data-h=kw_type>wchar_t</h-></code>?</h3>

<p><code><h- data-h=kw_type>char</h-></code> and <code><h- data-h=kw_type>wchar_t</h-></code> have existed for too long to make any deprecation
of their behavior realistic at this point.
There are approximately ten trillion lines of C++ code using <code><h- data-h=kw_type>char</h-></code><sup>[<i>citation needed</i>]</sup>.
</p>
<p>It would still be plausible to deprecate say, conversions between <code><h- data-h=kw_type>char</h-></code> and <code><h- data-h=id_type>charN_t</h-></code>.
However, there's a good chance that these are valid
because UTF-8 text is often stored in <code><h- data-h=kw_type>char</h-><h- data-h=sym_sqr>[</h-><h- data-h=sym_sqr>]</h-></code>,
and UTF-16 or UTF-32 text is often stored in <code><h- data-h=kw_type>wchar_t</h-><h- data-h=sym_sqr>[</h-><h- data-h=sym_sqr>]</h-></code>.
On the contrary, <code><h- data-h=kw_type>char8_t</h-></code> and <code><h- data-h=kw_type>char32_t</h-></code> almost certainly use different encodings.
</p>
<h3 id=integer-comparisons><a class=para href=#integer-comparisons></a>3.4. What about conversions with integers?</h3>

<p>It is quite common to compare character types to integer types.
For example, we may write <code><h- data-h=id>c</h-> <h- data-h=sym_op>&lt;=</h-> <h- data-h=num_deco>0x</h-><h- data-h=num>7f</h-></code>
to check whether a character falls into the basic latin block.
There is nothing exceptionally bug-prone about comparing with say,
<code><h- data-h=num_deco>0x</h-><h- data-h=num>00A0</h-></code> instead of <code><h- data-h=str_deco>U</h-><h- data-h=str_dlim>'</h-><h- data-h=esc>\</h-><h- data-h=esc>u00A0</h-><h- data-h=str_dlim>'</h-></code>,
so we are not interested in deprecating character/integer conversions.
</p>
<h3 id=after-deprecation><a class=para href=#after-deprecation></a>3.5. What comes after deprecation?</h3>

<p>The goal is to eventually remove these conversions entirely.
Since the behavior is
easily detected (<a href=#implementation-experience>§5. Implementation experience</a>) and
easily replaced (<a href=#replacement>§4.1. Replacement for deprecated behavior</a>),
removal should be feasible within one or two revisions of the language.
</p>
<p>Furthermore, I don't believe that having "tombstone behavior" would be necessary.
That is, allowing the conversion to happen but making the program ill-formed if it happens.
The reason is that <code><h- data-h=kw_type>char8_t</h-></code>, <code><h- data-h=kw_type>char16_t</h-></code>, and <code><h- data-h=kw_type>char32_t</h-></code>
rarely appear in overload sets that include types that are not characters.
</p><example-block><p><intro-></intro-> 
Without "tombstone behavior",
the following code would eventually change its meaning:
</p><code-block><h- data-h=kw_type>void</h-> <h- data-h=id>f</h-><h- data-h=sym_par>(</h-><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>any</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw_type>void</h-> <h- data-h=id>f</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>char32_t</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->

<h- data-h=kw_type>int</h-> <h- data-h=id>main</h-><h- data-h=sym_par>(</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Currently selects f(char32_t), would select f(std::any) in the future.</h->
    <h- data-h=id>f</h-><h- data-h=sym_par>(</h-><h- data-h=str_deco>u8</h-><h- data-h=str_dlim>'</h-><h- data-h=str>a</h-><h- data-h=str_dlim>'</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-> 
<h- data-h=sym_brac>}</h-></code-block>
</example-block>

<h2 id=impact-on-existing-code><a class=para href=#impact-on-existing-code></a>4. Impact on existing code</h2>

<p>It is not trivial to estimate how much code would be affected by a deprecation like this.
However, that is ultimately not what makes or breaks this proposal.
The goal is not to deprecate a rarely used feature to give it new meaning,
like <code><h- data-h=id>array</h-><h- data-h=sym_sqr>[</h-><h- data-h=num>0</h-><h- data-h=sym_punc>,</h-><h- data-h=num>1</h-><h- data-h=sym_sqr>]</h-></code> prior to <a href="https://wg21%2elink/P1161R3">[P1161R3]</a>.
</p>
<p><b>The goal is to deprecate a bug-prone and harmful feature to make the language safer.</b></p>

<p>The longer we wait, the more mistakes will be made using <code><h- data-h=kw_type>char8_t</h-></code> and other types.
C++ will undoubtedly get improved support for the Unicode character types over time,
making them used more frequently,
so we better deal with this problem now than never.
</p>
<h3 id=replacement><a class=para href=#replacement></a>4.1. Replacement for deprecated behavior</h3>

<p>If the new deprecation warnings spot a bug like in <a href=#introduction>§2. Introduction</a>,
some work will be required to fix it,
but the deprecation will have done its job.
</p>
<p>If the comparison is obviously safe, such as <code><h- data-h=id>c</h-> <h- data-h=sym_op>==</h-> <h- data-h=str_deco>U</h-><h- data-h=str_dlim>'</h-><h- data-h=str>0</h-><h- data-h=str_dlim>'</h-></code> with <code><h- data-h=kw_type>char8_t</h-> <h- data-h=id>c</h-></code>,
the resolution is usually trivial, like <code><h- data-h=id>c</h-> <h- data-h=sym_op>==</h-> <h- data-h=str_deco>u8</h-><h- data-h=str_dlim>'</h-><h- data-h=str>0</h-><h- data-h=str_dlim>'</h-></code>.
This could even be done automatically with tools like clang-tidy.
</p>

<h2 id=implementation-experience><a class=para href=#implementation-experience></a>5. Implementation experience</h2>

<p>Corentin Jabot has recently implemented a <tt->-Wcharacter-conversion</tt->
warning in Clang (<a href="https://github%2ecom/llvm/llvm-project/pull/138708">[ClangWarning]</a>), which is enabled by default.
You can test this at <a href="https://compiler-explorer%2ecom/z/8j9qqe8MY">[CompilerExplorer]</a>.
</p>
<p>However the warning is more conservative than the proposed deprecation;
it does not warn on "safe comparisons" (<a href=#safe-comparisons>§3.1. What about "safe" comparisons?</a>).
</p>
<h2 id=wording><a class=para href=#wording></a>6. Wording</h2>

<style>
  ins-block .para::before {
      display: none;
  }

  .stable-ref {
      float: right;
  }
</style>

<p>The following changes are relative to <a href="https://wg21%2elink/n5014">[N5014]</a>.
</p>
<p>Change <a href=https://eel.is/c++draft/basic.fundamental#9>[basic.fundamental] paragraph 9</a> as follows:
</p>
<diff-block>
<p><ins>The types <code><h- data-h=kw_type>char8_t</h-></code>, <code><h- data-h=kw_type>char16_t</h-></code>, and <code><h- data-h=kw_type>char32_t</h-></code>
are collectively called <i>Unicode character types</i>.</ins>
Type <code><h- data-h=kw_type>char8_t</h-></code> denotes a distinct type
whose underlying type is <code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>char</h-></code>.
Types <code><h- data-h=kw_type>char16_t</h-></code> and <code><h- data-h=kw_type>char32_t</h-></code> denote distinct types
whose underlying types are <code><h- data-h=id_type>uint_least16_t</h-></code> and <code><h- data-h=id_type>uint_least32_t</h-></code>,
respectively, in <tt->&lt;cstdint&gt;</tt->.
</p></diff-block>

<p>Change <a href=https://eel.is/c++draft/conv.integral#1>[conv.integral] paragraph 1</a> as follows:
</p>
<diff-block>
<p>A prvalue of an integer type <ins><code><h- data-h=id>S</h-></code></ins>
can be converted to a prvalue of another integer type <ins><code><h- data-h=id>D</h-></code></ins>.
<ins>The conversion is deprecated ([depr.conv.unicode]) if</ins>
</p><ul>
  <li><ins>
    <code><h- data-h=id>S</h-></code> is <code><h- data-h=kw_type>char8_t</h-></code> and
    <code><h- data-h=id>D</h-></code> is <code><h- data-h=kw_type>char16_t</h-></code> or <code><h- data-h=kw_type>char32_t</h-></code>,
    or <code><h- data-h=id>D</h-></code> is <code><h- data-h=kw_type>char8_t</h-></code> and
    <code><h- data-h=id>S</h-></code> is <code><h- data-h=kw_type>char16_t</h-></code> or <code><h- data-h=kw_type>char32_t</h-></code>; and
  </ins></li>
  <li><ins>
    the conversion is not necessitated by a <code><h- data-h=kw>static_cast</h-></code> (<a href=https://eel.is/c++draft/expr.static.cast>[expr.static.cast]</a>).
  </ins></li>
</ul>
<p><ins>[<i>Note</i>: 
This deprecation also applies to cv-qualified Unicode character types
because prvalues of such types are adjusted to cv-unqualified types; see <a href=https://eel.is/c++draft/expr.type>[expr.type]</a>.
 — <i>end note</i>]</ins><br/>
<del>A prvalue of an unscoped enumeration type can be converted to a prvalue of an integer type.</del>
</p></diff-block>

<p>Insert a new paragraph immediately following <a href=https://eel.is/c++draft/conv.integral#1>[conv.integral] paragraph 1</a>:
</p>
<ins-block>
<p>A prvalue of an unscoped enumeration type can be converted to a prvalue of an integer type.
</p></ins-block>

<p>Change <a href=https://eel.is/c++draft/expr.arith.conv#1>[expr.arith.conv] paragraph 1</a> as follows:
</p>
<diff-block>
<p>Many binary operators that expect operands of arithmetic or enumeration type
cause conversions and yield result types in a similar way.
The purpose is to yield a common type, which is also the type of the result.
This pattern is called the <i>usual arithmetic conversions</i>, which are defined as follows:
</p><ul>
  <li>
    The lvalue-to-rvalue conversion (<a href=https://eel.is/c++draft/conv.lval>[conv.lval]</a>) is applied to each operand
    and the resulting prvalues are used in place of the original operands
    for the remainder of this section.
  </li>
  <li>[…]</li>
  <li>
    Otherwise, each operand is converted to a common type <code><h- data-h=id>C</h-></code>.
    <ins>The conversion is deprecated if one operand is <code><h- data-h=kw_type>char8_t</h-></code>
    and the other operand is <code><h- data-h=kw_type>char16_t</h-></code> or <code><h- data-h=kw_type>char32_t</h-></code>.</ins>
    The integral promotion rules (<a href=https://eel.is/c++draft/conv.prom>[conv.prom]</a>) are used
    to determine a type <code><h- data-h=id>T1</h-></code> and type <code><h- data-h=id>T2</h-></code> for each operand.
    Then the following rules are applied to determine C:
    <ul>
        <li>[…]</li>
    </ul>
  </li>
</ul>
</diff-block>

<p>Insert a new subclause in <a href=https://eel.is/c++draft/depr>[depr]</a> between <a href=https://eel.is/c++draft/depr.local>[depr.local]</a> and <a href=https://eel.is/c++draft/depr.capture.this>[depr.capture.this]</a>,
containing a single paragraph:
</p>
<ins-block>
<h3 id=unicode-character-conversions-depr.conv.unicode><a class=para href=#unicode-character-conversions-depr%2econv%2eunicode></a>Unicode character conversions <span class=stable-ref>[depr.conv.unicode]</span></h3>

<p>The following conversions are deprecated:
</p><ul>
  <li>
    Integral conversions (<a href=https://eel.is/c++draft/conv.integral>[conv.integral]</a>)
    not necessitated by a <code><h- data-h=kw>static_cast</h-></code>,
    where the source type and destination type are
    two different Unicode character types (<a href=https://eel.is/c++draft/basic.fundamental>[basic.fundamental]</a>),
    one of which is <code><h- data-h=kw_type>char8_t</h-></code>.
  </li>
  <li>
    Usual arithmetic conversions (<a href=https://eel.is/c++draft/expr.arith.conv>[expr.arith.conv]</a>)
    where the operands
    after lvalue-to-rvalue conversion (<a href=https://eel.is/c++draft/conv.lval>[conv.lval]</a>)
    are two different Unicode character types,
    one of which is <code><h- data-h=kw_type>char8_t</h-></code>.
  </li>
</ul>
<p>[<i>Example</i>: 
</p><code-block class=borderless><h- data-h=kw_type>bool</h-> <h- data-h=id>is_oe</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>char8_t</h-> <h- data-h=id>c</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>c</h-> <h- data-h=sym_op>==</h-> <h- data-h=str_deco>U</h-><h- data-h=str_dlim>'</h-><h- data-h=str>ö</h-><h- data-h=str_dlim>'</h-><h- data-h=sym_punc>;</h->                     <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>deprecated</h-></f-serif>
<h- data-h=sym_brac>}</h->
<h- data-h=kw_type>void</h-> <h- data-h=id>f</h-><h- data-h=sym_par>(</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_type>char32_t</h-> <h- data-h=id>c</h-> <h- data-h=sym_op>=</h-> <h- data-h=str_deco>u8</h-><h- data-h=str_dlim>'</h-><h- data-h=str>x</h-><h- data-h=str_dlim>'</h-><h- data-h=sym_punc>;</h->                   <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>deprecated</h-></f-serif>
    <h- data-h=kw_type>char32_t</h-> <h- data-h=id>c</h-> <h- data-h=sym_op>=</h-> <h- data-h=str_deco>u</h-><h- data-h=str_dlim>'</h-><h- data-h=str>x</h-><h- data-h=str_dlim>'</h-><h- data-h=sym_punc>;</h->                    <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>OK, no </h-><code><h- data-h=kw_type>char8_t</h-></code><h- data-h=cmt> involved</h-></f-serif>
    <h- data-h=kw_type>char32_t</h-> <h- data-h=id>c</h-> <h- data-h=sym_op>=</h-> <h- data-h=str_dlim>'</h-><h- data-h=str>x</h-><h- data-h=str_dlim>'</h-><h- data-h=sym_punc>;</h->                     <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>OK, </h-></f-serif><code><h- data-h=kw_type>char</h-></code><f-serif><h- data-h=cmt> is not a Unicode character type</h-></f-serif>
    <h- data-h=id>is_oe</h-><h- data-h=sym_par>(</h-><h- data-h=str_deco>U</h-><h- data-h=str_dlim>'</h-><h- data-h=str>ö</h-><h- data-h=str_dlim>'</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->                          <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>deprecated</h-></f-serif>
    <h- data-h=id>is_oe</h-><h- data-h=sym_par>(</h-><h- data-h=kw>static_cast</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>char8_t</h-><h- data-h=sym_op>&gt;</h-><h- data-h=sym_par>(</h-><h- data-h=str_deco>U</h-><h- data-h=str_dlim>'</h-><h- data-h=str>ö</h-><h- data-h=str_dlim>'</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->    <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>OK, integral conversion necessitated by a </h-></f-serif><code><h- data-h=kw>static_cast</h-></code>
    <h- data-h=id>is_oe</h-><h- data-h=sym_par>(</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>char8_t</h-><h- data-h=sym_par>)</h-><h- data-h=str_deco>U</h-><h- data-h=str_dlim>'</h-><h- data-h=str>ö</h-><h- data-h=str_dlim>'</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->                 <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>OK, explicit conversion performed by a </h-></f-serif><code><h- data-h=kw>static_cast</h-></code>
<h- data-h=sym_brac>}</h-></code-block>
<p> — <i>end example</i>]
</p></ins-block>

<h2 id=references><a class=para href=#references></a>7. References</h2>


<div class=bib><div id=bib-item-N5014 class=bib-item>
<a href="https://wg21%2elink/n5014">[N5014]</a>
<span class=bib-author>Thomas Köppe.</span>
<span class=bib-title>Working Draft, Programming Languages — C++</span>
<span class=bib-date>2025-08-05</span>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg21/docs/papers/2025/n5014%2epdf" class=bib-link>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/n5014.pdf</a></div><div id=bib-item-µlight class=bib-item>
<a href="https://github%2ecom/Eisenwave/ulight">[µlight]</a>
<span class=bib-author>Jan Schultke.</span>
<span class=bib-title>ascii_chars.hpp utilities in µlight</span>
<a href="https://github%2ecom/Eisenwave/ulight" class=bib-link>https://github.com/Eisenwave/ulight</a></div><div id=bib-item-ClangWarning class=bib-item>
<a href="https://github%2ecom/llvm/llvm-project/pull/138708">[ClangWarning]</a>
<span class=bib-author>Corentin Jabot.</span>
<span class=bib-title>[Clang] Add warnings when mixing different charN_t types</span>
<a href="https://github%2ecom/llvm/llvm-project/pull/138708" class=bib-link>https://github.com/llvm/llvm-project/pull/138708</a></div><div id=bib-item-CompilerExplorer class=bib-item>
<a href="https://compiler-explorer%2ecom/z/8j9qqe8MY">[CompilerExplorer]</a>
<span class=bib-title>Demonstration of -Wcharacter-conversion</span>
<a href="https://compiler-explorer%2ecom/z/8j9qqe8MY" class=bib-link>https://compiler-explorer.com/z/8j9qqe8MY</a></div><div id=bib-item-P1161R3 class=bib-item>
<a href="https://wg21%2elink/P1161R3">[P1161R3]</a>
<span class=bib-author>Corentin Jabot.</span>
<span class=bib-title>Deprecate uses of the comma operator in subscripting expressions</span>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg21/docs/papers/2019/p1161r3%2ehtml" class=bib-link>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1161r3.html</a></div></div>
</main></body>
</html>
