<!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>Bit-precise integers</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>Bit-precise integers</h1>

<dl>
  <dt>Document number:</dt> <dd><a href=https://wg21.link/P3666R0>P3666R0</a></dd>
  <dt>Date:</dt>            <dd><tt->2025-09-11</tt-></dd>
  <dt>Audience:</dt>        <dd>SG6, SG22, EWG, LEWG</dd>
  <dt>Project:</dt>         <dd>ISO/IEC 14882 Programming Languages — C++, ISO/IEC JTC1/SC22/WG21</dd>
  <dt>Reply-to:</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/P3666/github class=sans>wg21.link/P3666/github</a></dd>
  <dt>Source:</dt>          <dd><a href=https://github.com/Eisenwave/cpp-proposals/blob/master/src/bitint.cow class=sans>github.com/Eisenwave/cpp-proposals/blob/master/src/bitint.cow</a></dd>
</dl>
<hr/>
</div>

<abstract-block><p><intro-></intro-> 
C23 has introduced so-called "bit-precise integers" into the language,
which should be brought to C++ for compatibility, among other reasons.
Following an exploration of possible designs in <a href="https://wg21%2elink/p3639r0">[P3639R0]</a> "The <tt->_BitInt</tt-> Debate",
this proposal introduces a new set of fundamental types to C++.
</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=2>2</div>
<a href=#introduction><h2>Introduction</h2></a>
<div class=toc-num data-level=3>2.1</div>
<a href=#c23><h3>C23</h3></a>
<div class=toc-num data-level=3>2.2</div>
<a href=#p3140r0-std::int_least128_t><h3>P3140R0 "<tt->std::int_least128_t</tt->"</h3></a>
<div class=toc-num data-level=3>2.3</div>
<a href=#p3639r0-the-_bitint-debate><h3>P3639R0 "The <tt->_BitInt</tt-> Debate"</h3></a>
<div class=toc-num data-level=2>3</div>
<a href=#motivation><h2>Motivation</h2></a>
<div class=toc-num data-level=3>3.1</div>
<a href=#computation-beyond-64-bits><h3>Computation beyond 64 bits</h3></a>
<div class=toc-num data-level=3>3.2</div>
<a href=#cornerstone-of-standard-library-facilities><h3>Cornerstone of standard library facilities</h3></a>
<div class=toc-num data-level=3>3.3</div>
<a href=#c-abi-compatibility><h3>C ABI compatibility</h3></a>
<div class=toc-num data-level=3>3.4</div>
<a href=#resolving-issues-with-the-current-integer-type-system><h3>Resolving issues with the current integer type system</h3></a>
<div class=toc-num data-level=3>3.5</div>
<a href=#portable-exact-width-integers><h3>Portable exact-width integers</h3></a>
<div class=toc-num data-level=2>4</div>
<a href=#core-design><h2>Core design</h2></a>
<div class=toc-num data-level=3>4.1</div>
<a href=#why-not-a-class-template><h3>Why not a class template?</h3></a>
<div class=toc-num data-level=4>4.1.1</div>
<a href=#full-c-compatibility-requires-fundamental-types><h4>Full C compatibility requires fundamental types</h4></a>
<div class=toc-num data-level=4>4.1.2</div>
<a href=#common-spelling-of-unsigned-_bitintn><h4>Common spelling of <code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-><h- data-h=sym_par>)</h-></code></h4></a>
<div class=toc-num data-level=4>4.1.3</div>
<a href=#c-compatibility-would-require-an-enormous-amount-of-operator-overloads-etc%2e><h4>C compatibility would require an enormous amount of operator overloads etc.</h4></a>
<div class=toc-num data-level=4>4.1.4</div>
<a href=#constructors-cannot-signal-narrowing><h4>Constructors cannot signal narrowing</h4></a>
<div class=toc-num data-level=4>4.1.5</div>
<a href=#tiny-integers-are-useful-in-c><h4>Tiny integers are useful in C++</h4></a>
<div class=toc-num data-level=4>4.1.6</div>
<a href=#special-deduction-rules><h4>Special deduction rules</h4></a>
<div class=toc-num data-level=4>4.1.7</div>
<a href=#special-overload-resolution-rankings><h4>Special overload resolution rankings</h4></a>
<div class=toc-num data-level=4>4.1.8</div>
<a href=#quality-of-implementation-requires-a-fundamental-type><h4>Quality of implementation requires a fundamental type</h4></a>
<div class=toc-num data-level=3>4.2</div>
<a href=#why-the-_bitint-keyword-spelling><h3>Why the <code><h- data-h=kw_type>_BitInt</h-></code> keyword spelling?</h3></a>
<div class=toc-num data-level=3>4.3</div>
<a href=#underlying-bitint><h3>Underlying type of enumerations</h3></a>
<div class=toc-num data-level=3>4.4</div>
<a href=#should-bit-precise-integers-be-optional><h3>Should bit-precise integers be optional?</h3></a>
<div class=toc-num data-level=3>4.5</div>
<a href=#bit-int-1><h3><tt->_BitInt(1)</tt-></h3></a>
<div class=toc-num data-level=3>4.6</div>
<a href=#undefined-behavior-on-signed-integer-overflow><h3>Undefined behavior on signed integer overflow</h3></a>
<div class=toc-num data-level=3>4.7</div>
<a href=#permissive-implicit-conversions><h3>Permissive implicit conversions</h3></a>
<div class=toc-num data-level=4>4.7.1</div>
<a href=#conversions-c-compatibility><h4>C compatibility</h4></a>
<div class=toc-num data-level=4>4.7.2</div>
<a href=#difficult-special-cases><h4>Difficulty of carving out exceptions in the language</h4></a>
<div class=toc-num data-level=4>4.7.3</div>
<a href=#conversions-low-hanging-fruits><h4>Picking some low-hanging fruits</h4></a>
<div class=toc-num data-level=4>4.7.4</div>
<a href=#conversions-conclusion><h4>Conclusion on implicit conversions</h4></a>
<div class=toc-num data-level=3>4.8</div>
<a href=#raising-the-bitint_maxwidth><h3>Raising the <tt->BITINT_MAXWIDTH</tt-></h3></a>
<div class=toc-num data-level=4>4.8.1</div>
<a href=#possible-increased-bitint_maxwidth-values><h4>Possible increased <tt->BITINT_MAXWIDTH</tt-> values</h4></a>
<div class=toc-num data-level=3>4.9</div>
<a href=#template-argument-deduction><h3>Template argument deduction</h3></a>
<div class=toc-num data-level=3>4.10</div>
<a href=#preprocessor><h3>No preprocessor changes, for better or worse</h3></a>
<div class=toc-num data-level=2>5</div>
<a href=#library-design><h2>Library design</h2></a>
<div class=toc-num data-level=3>5.1</div>
<a href=#naming-of-the-alias-template><h3>Naming of the alias template</h3></a>
<div class=toc-num data-level=4>5.1.1</div>
<a href=#why-no-_t-suffix><h4>Why no <code><h- data-h=id_type>_t</h-></code> suffix?</h4></a>
<div class=toc-num data-level=3>5.2</div>
<a href=#printing-support><h3><tt->format</tt->, <tt->to_chars</tt->, and <tt->to_string</tt-> support for bit-precise integers</h3></a>
<div class=toc-num data-level=3>5.3</div>
<a href=#preventing-iota-view-abi-break><h3>Preventing <tt->ranges::iota_view</tt-> ABI break</h3></a>
<div class=toc-num data-level=3>5.4</div>
<a href=#bit-precise-size_t-ptrdiff_t><h3>Bit-precise <code><h- data-h=id_type>size_t</h-></code>, <code><h- data-h=id_type>ptrdiff_t</h-></code></h3></a>
<div class=toc-num data-level=3>5.5</div>
<a href=#bitint-abs><h3>New <tt->abs</tt-> overload</h3></a>
<div class=toc-num data-level=3>5.6</div>
<a href=#bitint-cmath><h3>Using bit-precise integers in <tt->&lt;cmath&gt;</tt-> functions</h3></a>
<div class=toc-num data-level=3>5.7</div>
<a href=#random-support><h3>Lack of random number generation support</h3></a>
<div class=toc-num data-level=3>5.8</div>
<a href=#simd-support><h3><tt->simd</tt-> support for bit-precise integers</h3></a>
<div class=toc-num data-level=4>5.8.1</div>
<a href=#simd-design-problems><h4><tt->simd</tt-> design problems</h4></a>
<div class=toc-num data-level=4>5.8.2</div>
<a href=#simd-design-conclusion><h4><tt->simd</tt-> design conclusion</h4></a>
<div class=toc-num data-level=3>5.9</div>
<a href=#valarray-support><h3><tt->valarray</tt-> support for bit-precise integers</h3></a>
<div class=toc-num data-level=3>5.10</div>
<a href=#broadening-type-traits><h3>Broadening <tt->is_integral</tt-></h3></a>
<div class=toc-num data-level=3>5.11</div>
<a href=#misc-support><h3>Miscellaneous library support</h3></a>
<div class=toc-num data-level=3>5.12</div>
<a href=#feature-testing><h3>Feature testing</h3></a>
<div class=toc-num data-level=3>5.13</div>
<a href=#passing-bitint><h3>Passing <tt->bit_int</tt-> into standard library function templates</h3></a>
<div class=toc-num data-level=2>6</div>
<a href=#education><h2>Education</h2></a>
<div class=toc-num data-level=3>6.1</div>
<a href=#teaching-principles><h3>Teaching principles</h3></a>
<div class=toc-num data-level=2>7</div>
<a href=#implementation-experience><h2>Implementation experience</h2></a>
<div class=toc-num data-level=2>8</div>
<a href=#impact-on-the-standard><h2>Impact on the standard</h2></a>
<div class=toc-num data-level=3>8.1</div>
<a href=#impact-on-the-core-language><h3>Impact on the core language</h3></a>
<div class=toc-num data-level=3>8.2</div>
<a href=#impact-on-the-standard-library><h3>Impact on the standard library</h3></a>
<div class=toc-num data-level=2>9</div>
<a href=#wording><h2>Wording</h2></a>
<div class=toc-num data-level=3>9.1</div>
<a href=#core><h3>Core</h3></a>
<div class=toc-num data-level=4>9.1.1</div>
<a href=#lex%2eicon><h4>[lex.icon]</h4></a>
<div class=toc-num data-level=4>9.1.2</div>
<a href=#basic%2efundamental><h4>[basic.fundamental]</h4></a>
<div class=toc-num data-level=4>9.1.3</div>
<a href=#conv%2erank><h4>[conv.rank]</h4></a>
<div class=toc-num data-level=4>9.1.4</div>
<a href=#conv%2eprom><h4>[conv.prom]</h4></a>
<div class=toc-num data-level=4>9.1.5</div>
<a href=#dcl%2etype%2egeneral><h4>[dcl.type.general]</h4></a>
<div class=toc-num data-level=4>9.1.6</div>
<a href=#dcl%2etype%2esimple><h4>[dcl.type.simple]</h4></a>
<div class=toc-num data-level=4>9.1.7</div>
<a href=#dcl%2eenum><h4>[dcl.enum]</h4></a>
<div class=toc-num data-level=4>9.1.8</div>
<a href=#temp%2ededuct%2egeneral><h4>[temp.deduct.general]</h4></a>
<div class=toc-num data-level=4>9.1.9</div>
<a href=#temp%2ededuct%2etype><h4>[temp.deduct.type]</h4></a>
<div class=toc-num data-level=4>9.1.10</div>
<a href=#cpp%2epredefined><h4>[cpp.predefined]</h4></a>
<div class=toc-num data-level=3>9.2</div>
<a href=#library><h3>Library</h3></a>
<div class=toc-num data-level=4>9.2.1</div>
<a href=#version%2esyn><h4>[version.syn]</h4></a>
<div class=toc-num data-level=4>9.2.2</div>
<a href=#cstdint%2esyn><h4>[cstdint.syn]</h4></a>
<div class=toc-num data-level=4>9.2.3</div>
<a href=#climits%2esyn><h4>[climits.syn]</h4></a>
<div class=toc-num data-level=4>9.2.4</div>
<a href=#stdbit%2eh%2esyn><h4>[stdbit.h.syn]</h4></a>
<div class=toc-num data-level=4>9.2.5</div>
<a href=#range%2eiota%2eview><h4>[range.iota.view]</h4></a>
<div class=toc-num data-level=4>9.2.6</div>
<a href=#alg%2eforeach><h4>[alg.foreach]</h4></a>
<div class=toc-num data-level=4>9.2.7</div>
<a href=#alg%2esearch><h4>[alg.search]</h4></a>
<div class=toc-num data-level=4>9.2.8</div>
<a href=#alg%2ecopy><h4>[alg.copy]</h4></a>
<div class=toc-num data-level=4>9.2.9</div>
<a href=#alg%2efill><h4>[alg.fill]</h4></a>
<div class=toc-num data-level=4>9.2.10</div>
<a href=#alg%2egenerate><h4>[alg.generate]</h4></a>
<div class=toc-num data-level=4>9.2.11</div>
<a href=#charconv%2esyn><h4>[charconv.syn]</h4></a>
<div class=toc-num data-level=4>9.2.12</div>
<a href=#charconv%2eto%2echars><h4>[charconv.to.chars]</h4></a>
<div class=toc-num data-level=4>9.2.13</div>
<a href=#charconv%2efrom%2echars><h4>[charconv.from.chars]</h4></a>
<div class=toc-num data-level=4>9.2.14</div>
<a href=#string%2esyn><h4>[string.syn]</h4></a>
<div class=toc-num data-level=4>9.2.15</div>
<a href=#string%2econversions><h4>[string.conversions]</h4></a>
<div class=toc-num data-level=4>9.2.16</div>
<a href=#cmath%2esyn><h4>[cmath.syn]</h4></a>
<div class=toc-num data-level=4>9.2.17</div>
<a href=#c%2emath%2eabs><h4>[c.math.abs]</h4></a>
<div class=toc-num data-level=4>9.2.18</div>
<a href=#simd%2egeneral><h4>[simd.general]</h4></a>
<div class=toc-num data-level=4>9.2.19</div>
<a href=#numerics%2ec%2eckdint><h4>[numerics.c.ckdint]</h4></a>
<div class=toc-num data-level=4>9.2.20</div>
<a href=#atomics%2eref%2eint><h4>[atomics.ref.int]</h4></a>
<div class=toc-num data-level=4>9.2.21</div>
<a href=#atomics%2etypes%2eint><h4>[atomics.types.int]</h4></a>
<div class=toc-num data-level=2>10</div>
<a href=#acknowledgements><h2>Acknowledgements</h2></a>
<div class=toc-num data-level=2>11</div>
<a href=#references><h2>References</h2></a>
</div>

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

<p>This is the first revision.
</p>
<h2 id=introduction><a class=para href=#introduction></a>2. Introduction</h2>

<p>In distant history,
there have been various attempts at standardizing multi-precision integers in C++,
such as
<a href="https://wg21%2elink/n1692">[N1692]</a> "A Proposal to add the Infinite Precision Integer to the C++ Standard Library",
<a href="https://wg21%2elink/n1744">[N1744]</a> "Big Integer Library Proposal for C++0x", and
<a href="https://wg21%2elink/n4038">[N4038]</a> "Proposal for Unbounded-Precision Integer Types",
all of which have been abandoned by the authors.
However, there has always been some enthusiasm in the committee for such a feature.
</p>
<p>I am picking up where they have left off.
Whether this results in a C++ feature or adds corpses
to the graveyard of multi-precision papers remains to be seen.
</p>
<h3 id=c23><a class=para href=#c23></a>2.1. C23</h3>

<p>Recently, WG14's
<a href="https://open-std%2eorg/JTC1/SC22/WG14/www/docs/n2763%2epdf">[N2763]</a> introduced the <code><h- data-h=kw_type>_BitInt</h-></code> set of types to the C23 standard,
and <a href="https://open-std%2eorg/JTC1/SC22/WG14/www/docs/n2775%2epdf">[N2775]</a> further enhanced this feature with literal suffixes.
For example, this feature may be used as follows:
</p>
<code-block><h- data-h=cmt_dlim>//</h-><h- data-h=cmt> 8-bit unsigned integer initialized with value 255.</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> The literal suffix wb is unnecessary in this case.</h->
<h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>8</h-><h- data-h=sym_par>)</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>=</h-> <h- data-h=num_deco>0x</h-><h- data-h=num>FF</h-><h- data-h=num_deco>wb</h-><h- data-h=sym_punc>;</h-></code-block>

<p>In short, the behavior of these <dfn>bit-precise integers</dfn> is as follows:
</p>
<ul>
  <li>
    No integer promotion to <code><h- data-h=kw_type>int</h-></code> takes place.
  </li>
  <li>
    Mixed-signedness comparisons, implicit conversions,
    and other permissive feature are supported.
  </li>
  <li>
    They have lower conversion rank than standard integers,
    so an operation between <code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>8</h-><h- data-h=sym_par>)</h-></code> and <code><h- data-h=kw_type>int</h-></code> yields <code><h- data-h=kw_type>int</h-></code>,
    as does an operation with <code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-><h- data-h=sym_par>)</h-></code> where <code><h- data-h=id>N</h-></code> is the width of <code><h- data-h=kw_type>int</h-></code>.
    They only have greater conversion rank when their width is greater.
  </li>
  <li>
    Widths up to <code><h- data-h=id>BITINT_MAXWIDTH</h-></code> are allowed,
    with padding bits being added if needed.
    <code><h- data-h=id>BITINT_MAXWIDTH</h-></code> is at least <code><h- data-h=num>64</h-></code>.
  </li>
</ul>

<h3 id=p3140r0-std::int_least128_t><a class=para href=#p3140r0-std::int_least128_t></a>2.2. P3140R0 "<tt->std::int_least128_t</tt->"</h3>

<p>In parallel,
I proposed <a href="https://wg21%2elink/p3140r0">[P3140R0]</a> which would add 128-bit integers as <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>int_least128_t</h-></code>
to the C++ standard.
It became apparent to me that standardizing just a single width of 128
and not solving the <code><h- data-h=kw_type>_BitInt</h-></code> C compatibility problem would be futile,
so I've stepped away from the proposal.
However, the feedback and experience gained from P3140
made it well worth the time spent.
</p>
<h3 id=p3639r0-the-_bitint-debate><a class=para href=#p3639r0-the-_bitint-debate></a>2.3. P3639R0 "The <tt->_BitInt</tt-> Debate"</h3>

<p>I've subsequently proposed <a href="https://wg21%2elink/p3639r0">[P3639R0]</a> "The <tt->_BitInt</tt-> Debate",
which shifts the goal to compatibility with C's <code><h- data-h=kw_type>_BitInt</h-></code> type,
and attempts to answer whether the set of types corresponding to <code><h- data-h=kw_type>_BitInt</h-></code>
should be a class template or a family of fundamental types.
P3639R0 received much feedback in 2025.
First, from SG22:
</p>
<blockquote>
<p>The WG14 delegation to SG22 believes
that the C++ type family that deliberately corresponds to _BitInt
(perhaps via compatibility macros) should be... (Fundamental/Library)
</p>
<table class=five-way-poll>
  <tr><th>SF</th><th>F</th><th>N</th><th>L</th><th>SL</th></tr>
  <tr><td>8</td><td>1</td><td>1</td><td>0</td><td>0</td></tr>
</table>

<p>WG21
</p><table class=five-way-poll>
  <tr><th>SF</th><th>F</th><th>N</th><th>L</th><th>SL</th></tr>
  <tr><td>4</td><td>5</td><td>0</td><td>0</td><td>0</td></tr>
</table>
</blockquote>

<p>The overall sentiment in SG22 was that a fundamental type is "inevitable".
This is reflected in the polls.
SG6 also saw the paper, but had no clear opinion on the fundamental/library problem.
Last but not least, EWG also saw the paper in Sofia 2025,
with the following two polls:
</p>
<blockquote>
<p>P3639R0: EWG prefers that _BitInt-like type be a FUNDAMENTAL TYPE (in some form) in C++.
</p><table class=five-way-poll>
<tr><th>SF</th><th>F</th><th>N</th><th>A</th><th>SA</th></tr>
<tr><td>13</td><td>9</td><td>9</td><td>5</td><td>4</td></tr>
</table>

<p>Result: consensus
</p>
<p>P3639R0: EWG prefers that _BitInt-like type be a LIBRARY TYPE (in some form) in C++.
</p><table class=five-way-poll>
<tr><th>SF</th><th>F</th><th>N</th><th>A</th><th>SA</th></tr>
<tr><td>8</td><td>9</td><td>14</td><td>8</td><td>3</td></tr>
</table>

<p>Result: not consensus
</p></blockquote>

<p>While the general direction for the paper is clear (fundamental type),
there are many contentious design issues,
such as the minimum supported <tt->BITINT_WIDTH</tt->
or how permissive bit-precise integers should be with implicit conversions.
You can identify the most contentious problems as blocks such as:
</p>
<decision-block><p><intro-></intro-> 
This is an example.
</p></decision-block>

<h2 id=motivation><a class=para href=#motivation></a>3. Motivation</h2>

<h3 id=computation-beyond-64-bits><a class=para href=#computation-beyond-64-bits></a>3.1. Computation beyond 64 bits</h3>

<p>Computation beyond 64-bit bits, such as with 128-bits is immensely useful.
A large amount of motivation for 128-bit computation can be found in <a href="https://wg21%2elink/p3140r0">[P3140R0]</a>.
Computations in cryptography, such as for RSA require even 4096-bit integers.
</p>
<p>Even when performing most operations using 64-bit integers,
there are certain use cases where temporarily, twice the width is needed.
For example, the implementation of <code><h- data-h=id>linear_congruential_engine</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id_type>uint64_t</h-><h- data-h=sym_op>&gt;</h-></code>
requires the user of 128-bit arithmetic,
as does arithmetic with 64-bit
<a href=https://en.wikipedia.org/wiki/Fixed-point_arithmetic>fixed-point numbers (e.g. <tt->Q32.32</tt->)</a>.
</p>
<h3 id=cornerstone-of-standard-library-facilities><a class=para href=#cornerstone-of-standard-library-facilities></a>3.2. Cornerstone of standard library facilities</h3>

<p>There are various existing and possible feature
library facilities that would greatly benefit from an N-bit integer type:
</p>
<ul>
  <li>
    As mentioned above,
    the implementation of <code><h- data-h=id>linear_congruential_engine</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id_type>uint64_t</h-><h- data-h=sym_op>&gt;</h-></code>
    requires the use of 128-bit integers.
  </li>
  <li>
    <code><h- data-h=id>bitset</h-></code> has constructors taking <code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-></code> and a
    <code><h- data-h=id>to_ullong</h-></code> member function that converts from/to integers.
    This is clunky and limited considering that bitsets can be much larger
    than <code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-></code>.
    Bit-precise integers would be a superior alternative to <code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-></code> here.
  </li>
  <li>
    <a href="https://wg21%2elink/p3161r4">[P3161R4]</a> proposes library features such as <code><h- data-h=id>add_carry</h-></code>
    or <code><h- data-h=id>mul_wide</h-></code> which produce a wider integer result than the operands.
    For example:
    <code-block><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
<h- data-h=kw>struct</h-> <h- data-h=id>mul_wide_result</h-> <h- data-h=sym_brac>{</h->
  <h- data-h=id>T</h-> <h- data-h=id>low_bits</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id>T</h-> <h- data-h=id>high_bits</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>mul_wide_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>mul_wide</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=kw>noexcept</h-><h- data-h=sym_punc>;</h-></code-block>
    Proposals like these are arguably obsolete if the same operation can be
    expressed by simply casting the operands to an integer with double the width
    prior to the multiplication.
  </li>
</ul>

<h3 id=c-abi-compatibility><a class=para href=#c-abi-compatibility></a>3.3. C ABI compatibility</h3>

<p>C++ currently has no portable way to call C functions such as:
</p>
<code-block><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>32</h-><h- data-h=sym_par>)</h->  <h- data-h=id>plus</h-><h- data-h=sym_par>(</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>32</h-><h- data-h=sym_par>)</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h->  <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>32</h-><h- data-h=sym_par>)</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>128</h-><h- data-h=sym_par>)</h-> <h- data-h=id>plus</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>128</h-><h- data-h=sym_par>)</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>128</h-><h- data-h=sym_par>)</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<p>While one could rely on the ABI of <code><h- data-h=id_type>uint32_t</h-></code> and <code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>32</h-><h- data-h=sym_par>)</h-></code>
to be identical in the first overload,
there certainly is no way to portably invoke the second overload.
</p>
<p>This compatibility problem is not a hypothetical concern either; it is an urgent problem.
There are already targets with <code><h- data-h=kw_type>_BitInt</h-></code> supported by major compilers,
and used by C developers:
</p>
<style>
  .center {
    margin-left: auto;
    margin-right: auto;
  }
</style>

<table class=center>
  <tr>
    <th>Compiler</th>
    <th><tt->BITINT_MAXWIDTH</tt-></th>
    <th>Targets</th>
    <th>Languages</th>
  </tr>
  <tr>
    <td>clang 16+</td>
    <td><code><h- data-h=num>8</h-><h- data-h=num_dlim>'</h-><h- data-h=num>388</h-><h- data-h=num_dlim>'</h-><h- data-h=num>608</h-></code></td>
    <td>all</td>
    <td>C &amp; C++</td>
  </tr>
  <tr>
    <td>GCC 14+</td>
    <td><code><h- data-h=num>65</h-><h- data-h=num_dlim>'</h-><h- data-h=num>535</h-></code></td>
    <td>64-bit only</td>
    <td>C</td>
  </tr>
  <tr>
    <td>MSVC</td>
    <td>❌</td>
    <td>❌</td>
    <td>❌</td>
  </tr>
</table>

<h3 id=resolving-issues-with-the-current-integer-type-system><a class=para href=#resolving-issues-with-the-current-integer-type-system></a>3.4. Resolving issues with the current integer type system</h3>

<p><code><h- data-h=kw_type>_BitInt</h-></code> as standardized in C solves multiple issues that
the standard integers (<code><h- data-h=kw_type>int</h-></code> etc.) have.
Among other problems,
integer promotion can result in unexpected signedness changes.
</p>
<example-block><p><intro-></intro-> 
The following code has undefined behavior
if <code><h- data-h=kw_type>int</h-></code> is a 32-bit signed integer (which it is on many platforms).
</p>
<code-block><h- data-h=id_type>uint16_t</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>65</h-><h- data-h=num_dlim>'</h-><h- data-h=num>535</h-><h- data-h=sym_punc>;</h->
<h- data-h=id_type>uint16_t</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>;</h-></code-block>

<p>During the multiplication <code><h- data-h=id>x</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>x</h-></code>,
<code><h- data-h=id>x</h-></code> is promoted to <code><h- data-h=kw_type>int</h-></code>,
and the result of the multiplication <code><h- data-h=num>4</h-><h- data-h=num_dlim>'</h-><h- data-h=num>294</h-><h- data-h=num_dlim>'</h-><h- data-h=num>836</h-><h- data-h=num_dlim>'</h-><h- data-h=num>225</h-></code>
is not representable as a 32-bit signed integer.
Therefore, signed integer overflow takes places … given unsigned operands.
</p></example-block>

<example-block><p><intro-></intro-> 
The following code may have surprising effects
if <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>uint8_t</h-></code> is an alias for <code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>char</h-></code>
and gets promoted to <code><h- data-h=kw_type>int</h-></code>.
</p>
<code-block><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>uint8_t</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>=</h-> <h- data-h=num_deco>0b</h-><h- data-h=num>1111</h-><h- data-h=num_dlim>'</h-><h- data-h=num>0000</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>uint8_t</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>=</h-> <h- data-h=sym_op>~</h-><h- data-h=id>x</h-> <h- data-h=sym_op>&gt;&gt;</h-> <h- data-h=num>1</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> y = 0b1000'01111</h-></code-block>

<p>Surprisingly, <code><h- data-h=id>y</h-></code> is not <code><h- data-h=num_deco>0b</h-><h- data-h=num>111</h-></code>
because <code><h- data-h=id>x</h-></code> is promoted to <code><h- data-h=kw_type>int</h-></code> in <code><h- data-h=sym_op>~</h-><h- data-h=id>x</h-></code>,
so the subsequent right-shift by <code><h- data-h=num>1</h-></code> shifts one set bit into <code><h- data-h=id>y</h-></code> from the left.
Even more surprisingly, if we had used <code><h- data-h=kw>auto</h-></code> instead of <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>uint8_t</h-></code> for <code><h- data-h=id>y</h-></code>,
<code><h- data-h=id>y</h-></code> would be <code><h- data-h=sym_op>-</h-><h- data-h=num>121</h-></code>,
despite our code seemingly using only unsigned integers.
</p></example-block>

<p>Overall, the current integer promotion semantics are extremely surprising
and make it hard to write correct code involving promotable unsigned integers.
Promotion also makes it hard to expose small integers (e.g. 10-bit unsigned integer)
that exist in hardware (e.g. FPGA) in the language,
since all operations would be performed using <code><h- data-h=kw_type>int</h-></code>.
Unconventional hardware such as FPGAs are pillar of the motivation for <code><h- data-h=kw_type>_BitInt</h-></code>
laid out in <a href="https://open-std%2eorg/JTC1/SC22/WG14/www/docs/n2763%2epdf">[N2763]</a>.
</p>
<h3 id=portable-exact-width-integers><a class=para href=#portable-exact-width-integers></a>3.5. Portable exact-width integers</h3>

<p>There is no portable way to use an integer with exactly 32 bits in standard C++.
<code><h- data-h=id_type>int_least32_t</h-></code> and <code><h- data-h=kw_type>long</h-></code> may be wider,
and <code><h- data-h=id_type>int32_t</h-></code> is an optional type alias
which only exists if such an integer type has no padding bits.
Having additional non-padding bits may be undesirable when implementing serialization,
networking, etc. where the underlying file format or network protocol is specified
using exact widths.
</p>
<p>While most platforms support 32-bit integers as <code><h- data-h=id_type>int32_t</h-></code>,
their optionality is a problem for use in the standard library and other ultra-portable libraries.
There are many use cases where padding bits would be an acceptable sacrifice
in exchange for writing portable code,
and bit-precise integers fill that gap in the language.
</p>
<h2 id=core-design><a class=para href=#core-design></a>4. Core design</h2>

<p>The overall design strategy is as follows:
</p>
<ul>
  <li>
    The proposal is a C compatibility proposal first and foremost.
    Whenever possible, we match the behavior of the C type.
  </li>
  <li>
    The goal is to deliver a minimal viable product (MVP)
    which can be integrated into the standard as quickly as possible.
    This gives us plenty of time to add standard library support wherever desirable over time,
    as well as other convenience features surrounding <code><h- data-h=kw_type>_BitInt</h-></code>.
  </li>
</ul>

<h3 id=why-not-a-class-template><a class=para href=#why-not-a-class-template></a>4.1. Why not a class template?</h3>

<p><a href="https://wg21%2elink/p3639r0">[P3639R0]</a> explored in detail whether to make it a fundamental type or a library type.
Furthermore, feedback given by SG22 and EWG was to make it a fundamental type, not a library type.
This boils down to two plausible designs
(assuming <code><h- data-h=kw_type>_BitInt</h-></code> is already supported by the compiler), shown below.
</p>
<style>
  .toc h4 {
    margin-left: 1.5em;
  }
  .toc h5 {
    margin-left: 3em;
  }
  .toc h6 {
    margin-left: 4.5em;
  }

  #tony-table {
    margin-left: auto;
    margin-right: auto;
    width: 90%;
    table-layout: fixed;
  }
  #tony-table td {
    background-color: var(--deep-background-color);
    width: 50%;
  }
</style>

<table id=tony-table>
<tr>
    <th>𝔽 – Fundamental type</th>
    <th>𝕃 – Library type</th>
</tr>
<tr>
<td><code-block class=borderless><h- data-h=kw>template</h-> <h- data-h=sym_op>&lt;</h-><h- data-h=id_type>size_t</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h->
<h- data-h=kw>using</h-> <h- data-h=id>bit_int</h-> <h- data-h=sym_op>=</h->
    <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->




<h- data-h=kw>template</h-> <h- data-h=sym_op>&lt;</h-><h- data-h=id_type>size_t</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h->
<h- data-h=kw>using</h-> <h- data-h=id>bit_uint</h-> <h- data-h=sym_op>=</h->
    <h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block></td>
<td><code-block class=borderless><h- data-h=kw>template</h-> <h- data-h=sym_op>&lt;</h-><h- data-h=id_type>size_t</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h->
<h- data-h=kw>class</h-> <h- data-h=id>bit_int</h-> <h- data-h=sym_brac>{</h->
  <h- data-h=kw>private</h-><h- data-h=sym_punc>:</h->
    <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-><h- data-h=sym_par>)</h-> <h- data-h=id>_M_value</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>public</h-><h- data-h=sym_punc>:</h->
    <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> ...</h->
<h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw>template</h-> <h- data-h=sym_op>&lt;</h-><h- data-h=id_type>size_t</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h->
<h- data-h=kw>class</h-> <h- data-h=id>bit_uint</h->
  <h- data-h=sym_brac>{</h-> <h- data-h=cmt_dlim>/*</h-><h- data-h=cmt> ... </h-><h- data-h=cmt_dlim>*/</h-><h- data-h=sym_punc>;</h-> <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h-></code-block></td>
</tr>
</table>

<p>The reasons why we should prefer the left side are described in the following subsections.
</p>
<h4 id=full-c-compatibility-requires-fundamental-types><a class=para href=#full-c-compatibility-requires-fundamental-types></a>4.1.1. Full C compatibility requires fundamental types</h4>

<p><code><h- data-h=kw_type>_BitInt</h-></code> in C can be used as the type of a bit-field, among other places:
</p>
<code-block><h- data-h=kw>struct</h-> <h- data-h=id>S</h-> <h- data-h=sym_brac>{</h->
  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> 1. _BitInt as the underlying type of a bit-field</h->
  <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>32</h-><h- data-h=sym_par>)</h-> <h- data-h=id>x</h-> <h- data-h=sym_punc>:</h-> <h- data-h=num>10</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->

<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> 2. _BitInt in a switch statement</h->
<h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>32</h-><h- data-h=sym_par>)</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>10</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw_ctrl>switch</h-> <h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h-><h- data-h=sym_brac>}</h->

<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> 3. _BitInt used as a null pointer constant</h->
<h- data-h=kw_type>void</h-><h- data-h=sym_op>*</h-> <h- data-h=id>p</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>0</h-><h- data-h=num_deco>wb</h-><h- data-h=sym_punc>;</h->

<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> 4. _BitInt used as underlying type of enumeration</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>    (NOT valid now, but may be in the future)</h->
<h- data-h=kw>enum</h-> <h- data-h=id>S</h-> <h- data-h=sym_punc>:</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>32</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h-> <h- data-h=id>X</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>0</h-> <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h-></code-block>

<p>Since C++ does not support the use of class types in bit-fields,
such a <code><h- data-h=kw>struct</h-> <h- data-h=id>S</h-></code> could not be passed from C++ to a C API.
A developer would face <em>severe</em> difficulties
when porting C code which makes use of these capabilities to C++
and if bit-precise integers were a class type in C++.
</p>
<h4 id=common-spelling-of-unsigned-_bitintn><a class=para href=#common-spelling-of-unsigned-_bitintn></a>4.1.2. Common spelling of <code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-><h- data-h=sym_par>)</h-></code></h4>

<p>If bit-precise integers were class types in C++,
this would cause a serious problem with a common spelling
that can be used in both C and C++ headers,
even if there was a <code><h- data-h=mac>_BitInt</h-></code> compatibility macro.
</p>
<code-block><h- data-h=mac>#define _BitInt(...) std::bit_int&lt;__VA_ARGS__&gt;</h->

<h- data-h=kw_type>unsigned</h-> <h- data-h=mac>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>8</h-><h- data-h=sym_par>)</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> error: cannot combine 'unsigned' with class type</h-></code-block>

<p>There are some workarounds to the problem,
but they all seem unattractive:
</p>
<ul>
  <li>
    Permitting <code><h- data-h=kw_type>signed</h-></code> and <code><h- data-h=kw_type>unsigned</h-></code> to be combined with class types
    in general,
    perhaps with the effect of applying <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>make_signed</h-></code> and <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>make_unsigned</h-></code>.
    This would lead to a bifurcation of the language where both a builtin feature
    and a type trait achieve the same effect.
  </li>
  <li>
    "Blessing" the <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-></code> <g-term>type-name</g-term>
    so it can be combined with <code><h- data-h=kw_type>unsigned</h-></code>.
    This would be a highly unusual special case in the language.
  </li>
  <li>
    Making <code><h- data-h=mac>_BitInt(...)</h-></code> expand to an unspecified construct
    that can be combined with <code><h- data-h=kw_type>signed</h-></code> and <code><h- data-h=kw_type>unsigned</h-></code>.
    This means there needs to be a fundamental type,
    although that fundamental type only acts as a proxy for the <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-></code> class type.
    Once again, this comes off as an unusual special case.
  </li>
  <li>
    Introducing a <code><h- data-h=mac>_BitUint(...)</h-></code> macro for unsigned bit-precise integers,
    and insisting that both C and C++ developers use this for interoperability.
    This feels like an unnecessary burden for C developers
    considering that their spelling works perfectly fine
    and that we have other design options which keep C code intact.
  </li>
</ul>

<h4 id=c-compatibility-would-require-an-enormous-amount-of-operator-overloads-etc.><a class=para href=#c-compatibility-would-require-an-enormous-amount-of-operator-overloads-etc%2e></a>4.1.3. C compatibility would require an enormous amount of operator overloads etc.</h4>

<p>Integer types can be used in a large number of places within the language.
If we wanted a <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-></code> class type to be used in the same places
(which would be beneficial for C-interoperable code),
we would have to add a significant amount of operator overloads
and user-defined conversion functions:
</p>
<ul>
  <li>There are conversion to/from floating-point types and other integral types.</li>
  <li>There are conversion to/from enumeration types.</li>
  <li>
    There are conversion to/from pointers,
    at least for <code><h- data-h=kw_type>_BitInt</h-></code>s of the same width as <code><h- data-h=id_type>uintptr_t</h-></code>.
  </li>
  <li>
    Integers can be used to add offsets onto pointers, and by proxy,
    in the subscript operator of builtin arrays.
  </li>
  <li>
    Arithmetic operators can be used to operate between any mixture of arithmetic types,
    such as <code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>32</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>+</h-> <h- data-h=kw_type>float</h-></code>.
  </li>
</ul>

<p>Any discrepancies would lead to some code using bit-precise integers behaving
differently in C and C++, which is undesirable.
</p>
<p>Furthermore, the <code><h- data-h=id>wb</h-></code> <g-term>integer-suffix</g-term> for <code><h- data-h=kw_type>_BitInt</h-></code>
is fairly complicated to implement as a library feature
because the resulting type depends on the numeric value of the literal.
This means it would presumably be implemented like:
</p>
<code-block><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>char</h-><h- data-h=sym_op>...</h-> <h- data-h=id>Chars</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=kw>auto</h-> <h- data-h=kw>operator</h-><h- data-h=str_dlim>"</h-><h- data-h=str_dlim>"</h-><h- data-h=str_deco>wb</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> ... </h-><h- data-h=cmt_dlim>*/</h-> <h- data-h=sym_brac>}</h->
<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>char</h-><h- data-h=sym_op>...</h-> <h- data-h=id>Chars</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=kw>auto</h-> <h- data-h=kw>operator</h-><h- data-h=str_dlim>"</h-><h- data-h=str_dlim>"</h-><h- data-h=str_deco>WB</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> ... </h-><h- data-h=cmt_dlim>*/</h-> <h- data-h=sym_brac>}</h->
<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>char</h-><h- data-h=sym_op>...</h-> <h- data-h=id>Chars</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=kw>auto</h-> <h- data-h=kw>operator</h-><h- data-h=str_dlim>"</h-><h- data-h=str_dlim>"</h-><h- data-h=str_deco>uwb</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> ... </h-><h- data-h=cmt_dlim>*/</h-> <h- data-h=sym_brac>}</h->
<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>char</h-><h- data-h=sym_op>...</h-> <h- data-h=id>Chars</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=kw>auto</h-> <h- data-h=kw>operator</h-><h- data-h=str_dlim>"</h-><h- data-h=str_dlim>"</h-><h- data-h=str_deco>UWB</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> ... </h-><h- data-h=cmt_dlim>*/</h-> <h- data-h=sym_brac>}</h->
<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>char</h-><h- data-h=sym_op>...</h-> <h- data-h=id>Chars</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=kw>auto</h-> <h- data-h=kw>operator</h-><h- data-h=str_dlim>"</h-><h- data-h=str_dlim>"</h-><h- data-h=str_deco>uWB</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> ... </h-><h- data-h=cmt_dlim>*/</h-> <h- data-h=sym_brac>}</h->
<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>char</h-><h- data-h=sym_op>...</h-> <h- data-h=id>Chars</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=kw>auto</h-> <h- data-h=kw>operator</h-><h- data-h=str_dlim>"</h-><h- data-h=str_dlim>"</h-><h- data-h=str_deco>Uwb</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> ... </h-><h- data-h=cmt_dlim>*/</h-> <h- data-h=sym_brac>}</h-></code-block>

<p>Seeing that properly emulating C's behavior for <code><h- data-h=kw_type>_BitInt</h-></code> (and its suffixes)
requires a mountain of complicated operator overload sets,
user-defined conversion functions,
converting constructors, and
user-defined literals,
it seems unreasonable to go this direction.
</p>
<p>A major selling point of a library type is that library types have more teachable interfaces,
since the user simply needs to look at the declared members of the class
to understand how it works.
If the interface is a record-breaking convoluted mess,
this benefit is lost.
If we choose not to add all this functionality,
then we lose a large portion of C compatibility.
Either option is bad, and making <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-></code> a fundamental type
seems like the only way out.
</p>
<h4 id=constructors-cannot-signal-narrowing><a class=para href=#constructors-cannot-signal-narrowing></a>4.1.4. Constructors cannot signal narrowing</h4>

<p>Some C++ users prefer list initialization because it prevents narrowing conversion.
This can prevent some mistakes/questionable code:
</p>
<code-block><h- data-h=kw_type>unsigned</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>=</h-> <h- data-h=sym_op>-</h-><h- data-h=num>1</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> OK, x = UINT_MAX, but this looks weird</h->
<h- data-h=kw_type>unsigned</h-> <h- data-h=id>y</h-><h- data-h=sym_brac>{</h-> <h- data-h=sym_op>-</h-><h- data-h=num>1</h-> <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> error: narrowing conversion</h-></code-block>

<p>This would not be feasible if <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-></code> was a library type
because narrowing cannot be signaled by constructors.
Consider that <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-></code> and <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_uint</h-></code>
should have a non-explicit constructor (template)
accepting <code><h- data-h=kw_type>int</h-></code> (and other integral types) to enable compatibility in situations like:
</p>
<code-block><h- data-h=mac>#ifdef __cplusplus</h->
<h- data-h=kw>typedef</h-> <h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_uint</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>32</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>u32</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> C++</h->
<h- data-h=mac>#else</h->
<h- data-h=kw>typedef</h-> <h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>32</h-><h- data-h=sym_par>)</h-> <h- data-h=id>u32</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> C</h->
<h- data-h=mac>#endif</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Common C and C++ code, possibly in a header:</h->

<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> OK, converting int → u32.</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Using "incorrectly typed" zeros is fairly common, both in C and in C++.</h->
<h- data-h=id>u32</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>0</h-><h- data-h=sym_punc>;</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> OK, same conversion, but would be considered narrowing in C++.</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Not very likely to be written.</h->
<h- data-h=id>u32</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>=</h-> <h- data-h=sym_op>-</h-><h- data-h=num>1</h-><h- data-h=sym_punc>;</h-></code-block>

<p>If such a <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_uint</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>32</h-><h- data-h=sym_op>&gt;</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-><h- data-h=sym_par>)</h-></code> constructor existed,
the following C++ code would not raise any errors:
</p>
<code-block><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_uint</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>32</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>x</h-><h- data-h=sym_brac>{</h-> <h- data-h=num>0</h-> <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> OK, as expected</h->
<h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_uint</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>32</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>y</h-><h- data-h=sym_brac>{</h-> <h- data-h=sym_op>-</h-><h- data-h=num>1</h-> <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> OK?! But this looks narrowing!</h-></code-block>

<p>This code simply calls a <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_uint</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>32</h-><h- data-h=sym_op>&gt;</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-><h- data-h=sym_par>)</h-></code> constructor,
and while the initialization of <code><h- data-h=id>y</h-></code> is <em>spiritually</em> narrowing,
no narrowing conversion actually takes place.
In conclusion,
if <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-></code> was a library type,
C++ users who use this style would lose what they consider a valuable safety guarantee.
</p>
<note-block><p><intro-></intro-> 
It can be argued that using list-initialization for this purpose is an anti-pattern
and only solves a subset of the issues that compiler warnings and linter warnings should address.
Personally, I have no strong position on this issue.
</p></note-block>

<h4 id=tiny-integers-are-useful-in-c><a class=para href=#tiny-integers-are-useful-in-c></a>4.1.5. Tiny integers are useful in C++</h4>

<p>In some cases, tiny <code><h- data-h=id>bit_int</h-></code>'s may be useful as the underlying type of an enumeration:
</p>
<code-block><h- data-h=kw>enum</h-> <h- data-h=kw>struct</h-> <h- data-h=id>Direction</h-> <h- data-h=sym_punc>:</h-> <h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>2</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=sym_brac>{</h->
  <h- data-h=id>north</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>east</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>south</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>west</h-><h- data-h=sym_punc>,</h->
<h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h-></code-block>

<p>By using <code><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>2</h-><h- data-h=sym_op>&gt;</h-></code> rather than <code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>char</h-></code>,
every possible value has an enumerator.
If we used e.g. <code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>char</h-></code> instead,
there would be 252 other possible values that simply have no name,
and this may be detrimental to compiler optimization of <code><h- data-h=kw_ctrl>switch</h-></code> statements etc.
</p>
<note-block><p><intro-></intro-> 
Using bit-precise integers as the underlying type of enumerations
is not currently proposed (<a href=#underlying-bitint>§4.3. Underlying type of enumerations</a>).
However, it is likely that it will be supported in the future
(after some follow-up proposal),
so I still consider this motivation to be valid.
</p></note-block>

<h4 id=special-deduction-rules><a class=para href=#special-deduction-rules></a>4.1.6. Special deduction rules</h4>

<p>While this proposal focuses on the minimal viable product (MVP),
a possible future extension would be new deduction rules allowing the following code:
</p>
<code-block><h- data-h=kw>template</h-> <h- data-h=sym_op>&lt;</h-><h- data-h=id_type>size_t</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw_type>void</h-> <h- data-h=id>f</h-><h- data-h=sym_par>(</h-><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>x</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->

<h- data-h=id>f</h-><h- data-h=sym_par>(</h-><h- data-h=id_type>int32_t</h-><h- data-h=sym_par>(</h-><h- data-h=num>0</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> calls f&lt;32&gt;</h-></code-block>

<p>Being able to make such a call to <code><h- data-h=id>f</h-></code> is immensely useful because it would allow
for defining a single function template which may be called with every possible
signed integer type,
while only producing a single template instantiation
for <code><h- data-h=kw_type>int</h-></code>, <code><h- data-h=kw_type>long</h-></code>, and <code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>32</h-><h- data-h=sym_par>)</h-></code>,
as long as those three have the same width.
The prospect of being able to write bit manipulation utilities that simply accept
<code><h- data-h=id>bit_uint</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-></code> is quite appealing.
</p>
<p>If <code><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-></code> was a class type,
this would not work because template argument deduction would fail,
even if there existed an implicit conversion sequence from <code><h- data-h=id_type>int32_t</h-></code>
to <code><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>32</h-><h- data-h=sym_op>&gt;</h-></code>.
These kinds of deduction rules may be shutting the door on this mechanism forever.
</p>
<h4 id=special-overload-resolution-rankings><a class=para href=#special-overload-resolution-rankings></a>4.1.7. Special overload resolution rankings</h4>

<p>Yet another possible future extension would be rankings for overload resolution
that take integer width into account.
</p>
<example-block><p><intro-></intro-> 
Special overload rankings could make bit-precise integers
more easily interoperate with existing overload sets:
</p><code-block><h- data-h=kw>struct</h-> <h- data-h=id>QString</h-> <h- data-h=sym_brac>{</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> see Qt 6 documentation</h->
  <h- data-h=kw>static</h-> <h- data-h=id>QString</h-> <h- data-h=id>number</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>n</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>base</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>10</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>static</h-> <h- data-h=id>QString</h-> <h- data-h=id>number</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>long</h-> <h- data-h=id>n</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>base</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>10</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>static</h-> <h- data-h=id>QString</h-> <h- data-h=id>number</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=id>n</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>base</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>10</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> ...</h->
<h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->

<h- data-h=id>QString</h-><h- data-h=sym_op>::</h-><h- data-h=id>number</h-><h- data-h=sym_par>(</h-><h- data-h=num>0</h-><h- data-h=num_deco>wb</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> currently ambiguous, but could call QString::number(int)</h-></code-block>

<p>This could be valid if <code><h- data-h=id>number</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-><h- data-h=sym_par>)</h-></code> was considered a better match
on the basis that its width is closer to that of <code><h- data-h=num>0</h-><h- data-h=num_deco>wb</h-></code>.
Further disambiguation could be applied if <code><h- data-h=kw_type>int</h-></code> and <code><h- data-h=kw_type>long</h-></code> had the same width.
</p></example-block>

<example-block><p><intro-></intro-> 
Special overload rankings could make it possible to create non-template overload sets
that cover a greater range of widths:
</p><code-block><h- data-h=id>bit_uint</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>64</h-><h- data-h=sym_op>&gt;</h->  <h- data-h=id>clmul_wide</h-><h- data-h=sym_par>(</h-><h- data-h=id>bit_uint</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>32</h-><h- data-h=sym_op>&gt;</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>bit_uint</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>128</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>clmul_wide</h-><h- data-h=sym_par>(</h-><h- data-h=id>bit_uint</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>64</h-><h- data-h=sym_op>&gt;</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->

<h- data-h=id>clmul_wide</h-><h- data-h=sym_par>(</h-><h- data-h=num>128</h-><h- data-h=num_deco>wb</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> OK, calls clmul_wide(bit_uint&lt;32&gt;)</h-></code-block>
</example-block>

<p>These overload ranking rules would be difficult or impossible to define using a class type.
Of course, they are not proposed, and it's not certain whether such rules are desirable to have,
but it would be unfortunate to shut the door on these possible features forever.
</p>
<h4 id=quality-of-implementation-requires-a-fundamental-type><a class=para href=#quality-of-implementation-requires-a-fundamental-type></a>4.1.8. Quality of implementation requires a fundamental type</h4>

<p>While a library type <code><h- data-h=kw>class</h-> <h- data-h=id>bit_int</h-></code> gives the implementation
the option to provide no builtin support for bit-precise integers,
to achieve high-quality codegen,
a fundamental type is <em>inevitably</em> needed anyway.
</p>
<example-block><p><intro-></intro-> 
When an integer division has a constant divisor, like <code><h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=num>10</h-></code>,
it can be optimized to a fixed-point multiplication,
which is much cheaper:
</p>
<code-block><h- data-h=kw_type>unsigned</h-> <h- data-h=id>div10</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>unsigned</h-> <h- data-h=id>x</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=num>10</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-></code-block>

<p>For this operation, Clang emits the following assembly:
</p>
<code-block><h- data-h=id_labl>div10(unsigned int)</h-><h- data-h=sym_op>:</h->
        <h- data-h=asm_ins>mov</h->     <h- data-h=id_var>ecx</h-><h- data-h=sym_punc>,</h-> <h- data-h=id_var>edi</h->
        <h- data-h=asm_ins>mov</h->     <h- data-h=id_var>eax</h-><h- data-h=sym_punc>,</h-> <h- data-h=num>3435973837</h->
        <h- data-h=asm_ins>imul</h->    <h- data-h=id_var>rax</h-><h- data-h=sym_punc>,</h-> <h- data-h=id_var>rcx</h->
        <h- data-h=asm_ins>shr</h->     <h- data-h=id_var>rax</h-><h- data-h=sym_punc>,</h-> <h- data-h=num>35</h->
        <h- data-h=asm_ins>ret</h-></code-block>

<p>Basically, the result is rewritten as <code><h- data-h=id>x</h-> <h- data-h=sym_op>*</h-> <h- data-h=num>3435973837</h-><h- data-h=num_deco>ull</h-> <h- data-h=sym_op>&gt;&gt;</h-> <h- data-h=num>35</h-></code>.
This optimization is called <dfn>strength reduction</dfn>
and may lead to dramatically faster code,
especially when the hardware has no direct support for integer division.
Similarly, multiplication can be strength-reduced to bit-shifting
when a factor is a power of two,
remainder operations can be reduced to bitwise AND when the divisor is a power of two, etc.
</p>
<p>Performing strength reduction requires the compiler to be aware that a division is taking place,
and this fact is lost when division is implemented in software,
as a loop which expands to hundreds of IR instructions when unrolled.
</p></example-block>

<p>Furthermore, the compiler frontend needs to understand certain operations
to warn about obvious mistakes such as division by zero,
shifting by an overly large amount,
producing signed integer overflow unconditionally, etc.
Use of <code><h- data-h=kw>pre</h-></code> on e.g. <code><h- data-h=id>bit_int</h-><h- data-h=sym_op>::</h-><h- data-h=kw>operator</h-><h- data-h=sym_op>/</h-></code> cannot be used to achieve this
because numerics code needs to have no hardened preconditions and no contracts,
for performance reasons.
</p>
<p>Last but no least,
a fundamental type is needed to speed up constant evaluation.
Something like integer division between two <code><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>128</h-><h- data-h=sym_op>&gt;</h-></code>
may be much faster as a compiler-builtin operation
compared to constant-evaluating a "software division" loop with 128 iterations
necessary to implement <a href=https://en.wikipedia.org/wiki/Binary_number#Division>binary division</a>.
</p>
<p>If we accept the premise that a fundamental type is needed anyway
(possibly as an implementation detail of a class template),
then the class template actively harmful bloat:
</p><ul>
  <li>
    Any arithmetic operation needs to go through overload resolution,
    competing with countless other <code><h- data-h=kw>operator</h-><h- data-h=sym_op>+</h-></code>s
    (there are many in the standard library already).
    Even if implementers special-case these operations to circumvent the
    (usually awful) diagnostic quality of a failed call to <code><h- data-h=kw>operator</h-><h- data-h=sym_op>+</h-></code>,
    there remains substantial cost:
    overload resolution is expensive.
  </li>
  <li>
    Every distinct <code><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-></code> and <code><h- data-h=id>bit_uint</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-></code> would be a separate instantiation
    of a relatively large class template,
    which would undoubtedly add compilation cost.
  </li>
  <li>
    Invocations of member functions or operator overloads
    may add cost to debug builds and constant evaluation.
  </li>
</ul>


<h3 id=why-the-_bitint-keyword-spelling><a class=para href=#why-the-_bitint-keyword-spelling></a>4.2. Why the <code><h- data-h=kw_type>_BitInt</h-></code> keyword spelling?</h3>

<p>I also propose to standardize the keyword spelling
<code><h- data-h=kw_type>_BitInt</h-></code> and <code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-></code>.
I consider this to a "C compatibility spelling" rather than the preferred one
which is taught to C++ developers.
See also <a href=#teaching-principles>§6.1. Teaching principles</a>.
</p>
<p>While a similar approach could be taken
as with the <code><h- data-h=mac>_Atomic</h-></code> compatibility macro,
macros cannot be exported from modules,
and macros needlessly complicate the problem compared to a keyword.
Furthermore, to enable compiling shared C and C++ headers, all of the spellings
<code><h- data-h=kw_type>_BitInt</h-></code>, <code><h- data-h=kw_type>signed</h-> <h- data-h=kw_type>_BitInt</h-></code> and <code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-></code> need to be valid.
This goes far beyond the capabilities that a compatibility macro like <code><h- data-h=mac>_Atomic</h-></code>
can provide without language support.
If the <code><h- data-h=mac>_BitInt(...)</h-></code> macro simply expanded to <code><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>__VA_ARGS__</h-><h- data-h=sym_op>&gt;</h-></code>,
this may result in the ill-formed code <code><h- data-h=kw_type>signed</h-> <h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-></code>.
</p>
<p>The most plausible fix would be to create an exposition-only <code><i><h- data-h=id>bit-int</h-></i></code>
spelling to enable <code><h- data-h=kw_type>signed</h-> <i><h- data-h=id>bit-int&lt;N&gt;</h-></i></code>,
which makes our users beg the question:
</p>
<blockquote>
<p>Why is there a compatibility macro for an exposition-only keyword spelling?!
Why are we making everything more complicated by not just copying the keyword from C?!
Why is this exposition-only when it's clearly useful for users to spell?!
</p></blockquote>

<p>The objections to a keyword spelling are that it's not <em>really</em> necessary,
or that it "bifurcates" the language by having two spellings for the same thing,
or that those ugly C keywords should not exist in C++.
Ultimately, it's not the job of WG21 to police code style;
both spellings have a right to exist:
</p>
<ul>
  <li>
    The <code><h- data-h=id>bit_int</h-></code> alias template fits in aesthetically with the rest of the language,
    and conveys clearly (via "pointy brackets") that the given width is a constant expression.
  </li>
  <li>
    The <code><h- data-h=kw_type>_BitInt</h-></code> spelling is useful for writing C/C++-interoperable code,
    and C compatibility is an important design goal.
  </li>
</ul>

<p>It seems like both spellings are going to exist,
whether <code><h- data-h=kw_type>_BitInt</h-></code> is a keyword or compatibility macro.
Since there is no clear technical benefit to a macro,
the keyword is the <em>only</em> logical choice.
</p>
<note-block><p><intro-></intro-> 
Clang already supports the <code><h- data-h=kw_type>_BitInt</h-></code> keyword spelling as a compiler extensions,
so this is standardizing existing practice.
</p></note-block>

<h3 id=underlying-bitint><a class=para href=#underlying-bitint></a>4.3. Underlying type of enumerations</h3>

<p>The following C code is ill-formed:
</p>
<code-block><h- data-h=cmt_dlim>//</h-><h- data-h=cmt> error: '_BitInt(32)' is an invalid underlying type</h->
<h- data-h=kw>enum</h-> <h- data-h=id>S</h-> <h- data-h=sym_punc>:</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>32</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>0</h-> <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h-></code-block>

<p>There is no obvious reason why <code><h- data-h=kw_type>_BitInt</h-></code> must not be a valid underlying type.
However, since this feature is not needed for C compatibility,
I do not consider bit-precise integers as underlying types to be part of the MVP.
A follow-up proposal could add this feature later,
possibly in coordination with WG14.
</p>
<note-block><p><intro-></intro-> 
See <a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg14/www/docs/n3550%2epdf">[N3550]</a> §6.7.3.3 "Enumeration specifiers" for restrictions.
</p></note-block>

<p>This behavior should be mirrored.
</p>
<h3 id=should-bit-precise-integers-be-optional><a class=para href=#should-bit-precise-integers-be-optional></a>4.4. Should bit-precise integers be optional?</h3>

<p>As in C, <code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-><h- data-h=sym_par>)</h-></code> is only required to support <code><h- data-h=id>N</h-></code>
of at least <code><h- data-h=id>LLONG_WIDTH</h-></code>, which has a minimum of <code><h- data-h=num>64</h-></code>.
This makes <code><h- data-h=kw_type>_BitInt</h-></code> a semi-optional feature,
and it is reasonable to mandate its existence, even in freestanding platforms.
</p>
<p>Of course, this has the catch that <code><h- data-h=kw_type>_BitInt</h-></code> may be completely useless
for tasks like 128-bit computation.
As unfortunate as that is, the MVP should include no more than C actually mandates.
Mandating a greater minimum width could be done in a future proposal.
</p>
<h3 id=bit-int-1><a class=para href=#bit-int-1></a>4.5. <tt->_BitInt(1)</tt-></h3>

<p>C23 does not permit <code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>1</h-><h- data-h=sym_par>)</h-></code> but does permit <code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>1</h-><h- data-h=sym_par>)</h-></code>,
mostly for historical reasons
(C did not always requires two's complement representation for signed integers).
This is an irregularity that could make generic programming harder in C++.
</p>
<p>However, there are already plans to lift the restriction for C2y;
see <a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg14/www/docs/n3644%2epdf">[N3644]</a>.
Following v3 of the proposal,
<code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>1</h-><h- data-h=sym_par>)</h-></code> is expected to be valid type,
and <code><h- data-h=num>0</h-><h- data-h=num_deco>wb</h-></code> should be of type <code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>1</h-><h- data-h=sym_par>)</h-></code> rather than <code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>2</h-><h- data-h=sym_par>)</h-></code>.
That proposal also contains some practical motivation for why
a single-bit should be permitted.
</p>
<note-block><p><intro-></intro-> 
If <code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>1</h-><h- data-h=sym_par>)</h-></code> was allowed,
it would be able to represent the values <code><h- data-h=num>0</h-></code> and <code><h- data-h=sym_op>-</h-><h- data-h=num>1</h-></code>,
just like an <code><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-> <h- data-h=sym_punc>:</h-> <h- data-h=num>1</h-><h- data-h=sym_punc>;</h-></code> bit-field.
</p></note-block>

<h3 id=undefined-behavior-on-signed-integer-overflow><a class=para href=#undefined-behavior-on-signed-integer-overflow></a>4.6. Undefined behavior on signed integer overflow</h3>

<decision-block><p><intro-></intro-> 
Whether (and how) to address signed integer overflow in bit-precise integers
specifically is a contentious issue,
which has been discussed in great length.
EWG should decide whether to perpetuate undefined behavior
or to have different behavior for bit-precise integers.
</p></decision-block>

<p>I propose to perpetuate bit-precise integers having undefined behavior
on signed integer overflow, just like <code><h- data-h=kw_type>int</h-></code>, <code><h- data-h=kw_type>long</h-></code> etc.
This has a few reasons:
</p>
<ul>
  <li>
    bit-precise integers have undefined overflow in C,
    so this is what users are used to.
  </li>
  <li>
    "Solving" signed integer overflow for bit-precise integers is not part of the MVP.
    Undefined behavior can always be defined to do something else,
    so there is no urgent need for this paper to address this issue,
    rather than solving it in a follow-up paper.
  </li>
  <li>
    Signed integer overflow having undefined behavior is a much broader issue
    that should be looked at in general, for all integer types,
    not just bit-precise integer types.
    Perhaps hardened implementations could have wrapping overflow with erroneous behavior.
    In any case, the problem exceeds the scope of the paper.
  </li>
  <li>
    It is highly unusual that users would expect signed integer overflow to be well-behaved,
    such as having wrapping behavior.
    Adding two positive numbers and obtaining a negative number is not typically useful.
  </li>
  <li>
    The undefined behavior here is useful.
    It allows for optimizations such as converting <code><h- data-h=id>x</h-> <h- data-h=sym_op>+</h-> <h- data-h=num>3</h-> <h- data-h=sym_op>&lt;</h-> <h- data-h=num>0</h-></code> into <code><h- data-h=id>x</h-> <h- data-h=sym_op>&lt;</h-> <h- data-h=sym_op>-</h-><h- data-h=num>3</h-></code>.
  </li>
</ul>

<p>That being said,
much of the feedback surrounding bit-precise integers revolved around signed integer overflow.
If we were to make signed integer overflow <em>not</em> undefined for bit-precise integers,
there are two options that may find consensus:
</p>
<ul>
  <li>
    Make signed integer overflow wrapping.
    In other words, most operations would be performed as if by casting to the corresponding
    unsigned type, performing the operation, and casting back.
  </li>
  <li>
    Make signed integer overflow wrapping <em>and</em> erroneous.
    This is mirroring Rust's behavior,
    and would typically be implemented by detecting overflow
    on debug builds and in constant evaluation,
    but ignoring it and letting it wrap in release builds.
  </li>
</ul>

<h3 id=permissive-implicit-conversions><a class=para href=#permissive-implicit-conversions></a>4.7. Permissive implicit conversions</h3>

<p>Just like any other integral type,
the proposal makes bit-precise integers quite permissive when it comes to implicit conversions.
This is disappointing to anyone who wants bit-precise integers
to be a much "stricter" or "safer" alternative to standard integers,
but it is arguably the better design
for various reasons.
</p>
<decision-block><p><intro-></intro-> 
This is a contentious issue,
and feedback was given that implicit conversions should be limited
for bit-precise integers.
The idea of limiting implicit conversions was also a selling point of <a href="https://wg21%2elink/p3639r0">[P3639R0]</a>.
</p>
<p>There are several plausible directions:
</p><ul>
  <li>
    Perpetuate implicit conversions of the standard integers.
    This is the current design of the proposal;
    see rationale below.
  </li>
  <li>
    Limit implicit conversions for bit-precise integers.
    For example, converting <code><h- data-h=kw_type>int</h-></code> to <code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>1</h-><h- data-h=sym_par>)</h-></code> could be invalid.
  </li>
  <li>
    Perpetuate implicit conversions of standard integers,
    but also add a library wrapper or another <code><h- data-h=id>_BitIntStrict</h-></code> type family
    with much more restrictive semantics.
  </li>
</ul>
</decision-block>

<h4 id=conversions-c-compatibility><a class=para href=#conversions-c-compatibility></a>4.7.1. C compatibility</h4>

<p>Firstly, the point of perpetuating implicit conversions
is to mirror the C semantics as closely as possible,
which leads to few or no surprises when porting code between the languages,
or when writing C-interoperable headers.
</p>
<p>If we look at how C users use <code><h- data-h=kw_type>_BitInt</h-></code>,
<a href="https://github.com/search?q=%22_BitInt%22+language%3AC+&type=code">GitHub code search for <tt->"_BitInt" language:C</tt-></a> yields examples such as:
</p>
<blockquote>
<code-block><h- data-h=cmt_dlim>//</h-><h- data-h=cmt> mixing signed and unsigned bit-precise integers</h->
<h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>128</h-><h- data-h=sym_par>)</h-> <h- data-h=id>max128s</h-> <h- data-h=sym_op>=</h-> <h- data-h=num_deco>0x</h-><h- data-h=num>7FFF</h-><h- data-h=num_dlim>'</h-><h- data-h=num>FFFF</h-><h- data-h=num_dlim>'</h-><h- data-h=num>FFFF</h-><h- data-h=num_dlim>'</h-><h- data-h=num>FFFF</h-><h- data-h=num_dlim>'</h-><h- data-h=num>FFFF</h-><h- data-h=num_dlim>'</h-><h- data-h=num>FFFF</h-><h- data-h=num_dlim>'</h-><h- data-h=num>FFFF</h-><h- data-h=num_dlim>'</h-><h- data-h=num>FFFF</h-><h- data-h=num_deco>wb</h-><h- data-h=sym_punc>;</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> mixing bit-precise and standard integers</h->
<h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>4</h-><h- data-h=sym_par>)</h-> <h- data-h=id>a</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>1</h-><h- data-h=num_deco>u</h-><h- data-h=sym_punc>;</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> mixing bit-precise and standard integers of different signedness</h->
<h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>total</h-><h- data-h=sym_par>)</h-> <h- data-h=id>bit</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>1</h-><h- data-h=sym_punc>;</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> ... including cases where initialization does not preserve values</h->
<h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>3</h-><h- data-h=sym_par>)</h-> <h- data-h=id>max3u</h-> <h- data-h=sym_op>=</h-> <h- data-h=sym_op>-</h-><h- data-h=num>1</h-><h- data-h=sym_punc>;</h-></code-block>
</blockquote>

<p>If we were to make implicit conversions much more restrictive on the C++ side,
it would become very easy to slip up and accidentally write a header
that does not also compile in C++.
</p>
<h4 id=difficult-special-cases><a class=para href=#difficult-special-cases></a>4.7.2. Difficulty of carving out exceptions in the language</h4>

<p>Writing C++ code involving bit-precise integers would be
quite annoying and "flag" many harmless cases
if the rules were too strict.
</p>
<example-block><p><intro-></intro-> 
The following line of code would not compile if converting from <code><h- data-h=kw_type>int</h-></code>
to <code><h- data-h=id>bit_uint</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>8</h-><h- data-h=sym_op>&gt;</h-></code> was unconditionally ill-formed.
</p><code-block><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_uint</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>8</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>0</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> error?</h-></code-block>

<p><code><h- data-h=num>0</h-></code> is "incorrectly signed" for <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_uint</h-></code>,
and the conversion from <code><h- data-h=kw_type>int</h-></code> to <code><h- data-h=id>bit_uint</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>8</h-><h- data-h=sym_op>&gt;</h-></code> is not value-preserving generally,
but writing code like this is perfectly reasonable.
</p>
<p>The workaround would be to use correct literals, such as:
</p><code-block><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_uint</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>8</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>0</h-><h- data-h=num_deco>uwb</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> OK, conversion bit_uint&lt;1&gt; → bit_uint&lt;8&gt;</h-></code-block>
</example-block>

<p>To combat this problem,
it would be necessary to carve out various special cases.
For example, permitting value-preserving conversions with constant expressions
would prevent the example above from being flagged.
</p>
<note-block><p><intro-></intro-> 
There is precedent for such special casing of value-preserving conversions.
Specifically, see mentions of "narrowing" in
<a href=https://eel.is/c++draft/dcl.init.list>[dcl.init.list]</a>, <a href=https://eel.is/c++draft/expr.spaceship>[expr.spaceship]</a>, and <a href=https://eel.is/c++draft/expr.const>[expr.const]</a>.
</p></note-block>

<p>However, such special cases are insufficient to cover <em>all</em> harmless cases.
</p>
<example-block><p><intro-></intro-> 
</p><code-block><h- data-h=kw_type>void</h-> <h- data-h=id>for_each_cell</h-><h- data-h=sym_par>(</h-><h- data-h=id>vec3</h-> <h- data-h=id>x</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>int</h-> <h- data-h=id>i</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>0</h-><h- data-h=sym_punc>;</h-> <h- data-h=id>i</h-> <h- data-h=sym_op>&lt;</h-> <h- data-h=num>3</h-><h- data-h=sym_punc>;</h-> <h- data-h=sym_op>++</h-><h- data-h=id>i</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=id>do_something</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_sqr>[</h-><h- data-h=id>i</h-><h- data-h=sym_sqr>]</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=sym_brac>}</h->
<h- data-h=sym_brac>}</h-></code-block>

<p>Even though <code><h- data-h=id>i</h-></code> is not a constant expression,
<code><h- data-h=id>x</h-><h- data-h=sym_sqr>[</h-><h- data-h=id>i</h-><h- data-h=sym_sqr>]</h-></code> will "just work" no matter what integer type <code><h- data-h=id>vec3</h-><h- data-h=sym_op>::</h-><h- data-h=kw>operator</h-><h- data-h=sym_sqr>[</h-><h- data-h=sym_sqr>]</h-></code> accepts.
</p></example-block>

<p>Existing C++ code bases that have not used flags such as <tt->-Wconversion</tt->
from the start are likely filled with many such harmless cases of mixed-sign
implicit conversions.
If bit-precise integer types were introduced into these code bases,
refactoring effort may be unacceptable.
</p>
<p>Furthermore, discrepancies between the standard integers and bit-precise integers
would make it much harder to write generic code:
</p>
<example-block><p><intro-></intro-> 
The following function template may be instantiated with any integral type <code><h- data-h=id>T</h-></code>,
but the instantiation would be ill-formed for <code><h- data-h=id>T</h-> <h- data-h=sym_op>=</h-> <h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>8</h-><h- data-h=sym_par>)</h-></code>
with restrictive implicit conversions:
</p>
<code-block><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>integral</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
<h- data-h=id>T</h-> <h- data-h=id>div_ceil</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> performs integer division, rounding to +inf</h->
  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> ⚠️ Could be mixed-sign comparison:</h->
  <h- data-h=kw_type>bool</h-> <h- data-h=id>quotient_positive</h-> <h- data-h=sym_op>=</h-> <h- data-h=sym_par>(</h-><h- data-h=id>x</h-> <h- data-h=sym_op>^</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&gt;=</h-> <h- data-h=num>0</h-><h- data-h=sym_punc>;</h->
  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> ⚠️ Could be mixed-sign comparison</h->
  <h- data-h=kw_type>bool</h-> <h- data-h=id>adjust</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>!=</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>&amp;&amp;</h-> <h- data-h=id>quotient_positive</h-><h- data-h=sym_punc>;</h->
  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> ⚠️ Could be mixed-sign addition between int (0 or 1)</h->
  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt>    and unsigned _BitInt(N) "x / y":</h->
  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> ⚠️ Could be lossy conversion when returning: int → unsigned _BitInt</h->
  <h- data-h=kw_ctrl>return</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>+</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>adjust</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-></code-block>

<p>Literally every statement of this template may fail to compile when <code><h- data-h=id>T</h-> <h- data-h=sym_op>=</h-> <h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>8</h-><h- data-h=sym_par>)</h-></code>,
depending on how strict implicit conversions are.
I conjecture that there are vast amounts of templates like <code><h- data-h=id>div_ceil</h-></code>.
To accommodate bit-precise integers in this function, a rewrite is necessary:
</p>
<code-block><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>integral</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
<h- data-h=id>T</h-> <h- data-h=id>div_ceil</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
<ins>  <h- data-h=kw>constexpr</h-> <h- data-h=kw>auto</h-> <h- data-h=id>zero</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>T</h-><h- data-h=sym_par>(</h-><h- data-h=num>0</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></ins>
  <h- data-h=kw_type>bool</h-> <h- data-h=id>quotient_positive</h-> <h- data-h=sym_op>=</h-> <h- data-h=sym_par>(</h-><h- data-h=id>x</h-> <h- data-h=sym_op>^</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&gt;=</h-> <del><h- data-h=num>0</h-></del> <ins><h- data-h=id>zero</h-></ins><h- data-h=sym_punc>;</h->
  <h- data-h=kw_type>bool</h-> <h- data-h=id>adjust</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>!=</h-> <del><h- data-h=num>0</h-></del> <ins><h- data-h=id>zero</h-></ins> <h- data-h=sym_op>&amp;&amp;</h-> <h- data-h=id>quotient_positive</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw_ctrl>return</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>+</h-> <del><h- data-h=kw_type>int</h-></del> <ins><h- data-h=id>T</h-></ins><h- data-h=sym_par>(</h-><h- data-h=id>adjust</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-></code-block>
</example-block>

<example-block><p><intro-></intro-> 
The following function template involves a mixed-sign operation,
but is entirely harmless for any type <code><h- data-h=id>T</h-></code>:
</p>
<code-block><h- data-h=kw>constexpr</h-> <h- data-h=kw_type>unsigned</h-> <h- data-h=id>mask</h-> <h- data-h=sym_op>=</h-> <h- data-h=num_deco>0x</h-><h- data-h=num>f</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>T</h-> <h- data-h=id>integer</h-> <h- data-h=sym_op>=</h-> <h- data-h=cmt_dlim>/*</h-><h- data-h=cmt> ... </h-><h- data-h=cmt_dlim>*/</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>x</h-> <h- data-h=sym_op>&amp;=</h-> <h- data-h=id>mask</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> equivalent to x = x &amp; mask;</h-></code-block>

<p>Even if <code><h- data-h=id>x</h-></code> is signed instead of unsigned,
<code><h- data-h=id>x</h-> <h- data-h=sym_op>&amp;</h-> <h- data-h=id>mask</h-></code> produces a mathematically identical result.
</p></example-block>

<h4 id=conversions-low-hanging-fruits><a class=para href=#conversions-low-hanging-fruits></a>4.7.3. Picking some low-hanging fruits</h4>

<p>While conversions between bit-precise integers
and other signed or unsigned integer could be difficult to restrict due to the reasons
above,
other conversions are much more rare
and could more easily be restricted:
</p>
<ul>
  <li>Conversions between bit-precise integers and <code><h- data-h=kw_type>bool</h-></code>.</li>
  <li>Conversions between bit-precise integers and character types.</li>
  <li>Conversions between bit-precise integers and floating-point types.</li>
</ul>

<p>It would be reasonable to ban these conversions unconditionally
because they are likely to be category errors.
</p>
<bug-block><p><intro-></intro-> 
Consider the "easter egg" discovered in <a href=https://cplusplus.com/forum/general/105627/ class=sans>cplusplus.com/forum/general/105627/</a>:
</p>
<blockquote>
<p>I was fixing a couple of minor bugs in a program I've been working on,
when I made the mistake of typing <code><h- data-h=id>cout</h-><h- data-h=sym_op>&lt;&lt;</h-><h- data-h=id>string</h-><h- data-h=sym_par>(</h-><h- data-h=str_dlim>'</h-><h- data-h=esc>\</h-><h- data-h=esc>n</h-><h- data-h=str_dlim>'</h-><h- data-h=sym_punc>,</h-> <h- data-h=num>1</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code>
instead of <code><h- data-h=id>cout</h-><h- data-h=sym_op>&lt;&lt;</h-><h- data-h=id>string</h-><h- data-h=sym_par>(</h-><h- data-h=num>1</h-><h- data-h=sym_punc>,</h-><h- data-h=str_dlim>'</h-><h- data-h=esc>\</h-><h- data-h=esc>n</h-><h- data-h=str_dlim>'</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code></p>

<p>I didn't get any compile errors and the programs reaction gave me a bit of a laugh.
Instead of the blank line I wanted to put in, I got <tt->:):):):):):):):):):)</tt-> (10 of them).
It just made me wonder as a relative C++ beginner what other "easter eggs" are there
that people might feel like sharing.
</p></blockquote>

<p>It turns out that <code><h- data-h=id>string</h-><h- data-h=sym_par>(</h-><h- data-h=str_dlim>'</h-><h- data-h=esc>\</h-><h- data-h=esc>n</h-><h- data-h=str_dlim>'</h-><h- data-h=sym_punc>,</h-> <h- data-h=num>1</h-><h- data-h=sym_par>)</h-></code> is not an "easter egg",
it just results in the Windows terminal displaying a <code><h- data-h=kw_type>char</h-><h- data-h=sym_par>(</h-><h- data-h=num>1</h-><h- data-h=sym_par>)</h-></code> as "<tt->:)</tt->"
ten times.
The <code><h- data-h=id>string</h-><h- data-h=sym_par>(</h-><h- data-h=id_type>size_t</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_par>)</h-></code> overload is called,
and since the <code><h- data-h=str_dlim>'</h-><h- data-h=esc>\</h-><h- data-h=esc>n</h-><h- data-h=str_dlim>'</h-></code> and <code><h- data-h=num>1</h-></code> can be converted to <code><h- data-h=id_type>size_t</h-></code> and <code><h- data-h=kw_type>char</h-></code>
without any change in value,
compilers generally don't raise a warning, even with <code><h- data-h=sym_op>-</h-><h- data-h=id>Wconversion</h-> <h- data-h=id>enabled</h-></code>.
</p></bug-block>

<p>The least harmful of these conversions is a value-preserving
conversion from a bit-precise integer to a floating-point type.
However, at best, these lack clarity of intent.
</p>
<example-block><p><intro-></intro-> 
Consider a code base with the following two functions computing <math display=inline><msqrt><mi>x</mi></msqrt></math>:
</p><code-block><h- data-h=kw_type>int</h-> <h- data-h=id>isqrt</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw_type>double</h-> <h- data-h=id>sqrt</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>double</h-> <h- data-h=id>x</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>
<p>When the user calls <code><h- data-h=id>sqrt</h-></code> with an integer operand,
are we sure that this decision was made intentionally?
Is the author unaware that there is a separate function giving the integer results,
or do they actually need the fractional part,
and that is why they called the <code><h- data-h=kw_type>double</h-></code> overload?
Even if the author wrote <code><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-><h- data-h=sym_par>)</h-> <h- data-h=id>sqrt</h-><h- data-h=sym_par>(</h-><h- data-h=cmt_dlim>/*</h-><h- data-h=cmt> ... </h-><h- data-h=cmt_dlim>*/</h-><h- data-h=sym_par>)</h-></code>,
this could plausibly be done due to performance considerations.
</p>
<p>Similarly, calling <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>sqrt</h-></code> with an integer operand could be a major performance bug
on a 32-bit platform with 32-bit <code><h- data-h=kw_type>float</h-></code> and 64-bit <code><h- data-h=kw_type>double</h-></code>,
considering that this is equivalent to calling <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>sqrt</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>double</h-><h- data-h=sym_par>)</h-></code>.
Perhaps calling <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>sqrt</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>float</h-><h- data-h=sym_par>)</h-></code> was intended.
</p>
<p>Conversely, if the author called <code><h- data-h=id>isqrt</h-><h- data-h=sym_par>(</h-><h- data-h=num>10</h-><h- data-h=num_dlim>.</h-><h- data-h=num_deco>f</h-><h- data-h=sym_par>)</h-></code>,
the <code><h- data-h=kw_type>float</h-></code> → <code><h- data-h=kw_type>int</h-></code> conversion may be value-preserving,
but this call is almost certainly a mistake.
The author likely expected to obtain <code><h- data-h=num>3</h-><h- data-h=num_dlim>.</h-><h- data-h=num>1623</h-><h- data-h=num_deco>f</h-></code>, judging by the operand.
</p></example-block>

<h4 id=conversions-conclusion><a class=para href=#conversions-conclusion></a>4.7.4. Conclusion on implicit conversions</h4>

<p>In conclusion, discrepancies between the standard integers and bit-precise
integers are undesirable;
they introduce a lot of unnecessary problems.
There are many harmless operations like <code><h- data-h=id>T</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>0</h-><h- data-h=sym_punc>;</h-></code> and <code><h- data-h=id>x</h-> <h- data-h=sym_op>&amp;</h-> <h- data-h=id>mask</h-></code>
where mixing signedness is okay,
and not every user wants to have warnings, let alone errors for these.
Especially errors would make it hard to write headers that compile both in C and in C++.
</p>
<p>The final nail in the coffin is that if the user wants implicit conversions to be restricted,
they have the freedom to add those restrictions via compiler warnings and linter checks.
Having these restrictions standardized in the language robs the user of choice.
If C++26 profiles make progress,
it is likely that C++ will have profiles which restrict implicit conversions,
giving users a standard way to opt into diagnostics.
</p>
<p>However, the decision to permit implicit conversions is not set in stone.
Especially the conversions described in <a href=#conversions-low-hanging-fruits>§4.7.3. Picking some low-hanging fruits</a>
could be banned for bit-precise integers without much of an issue.
</p>
<h3 id=raising-the-bitint_maxwidth><a class=para href=#raising-the-bitint_maxwidth></a>4.8. Raising the <tt->BITINT_MAXWIDTH</tt-></h3>

<p>The proposal currently does not seek to increase the <code><h- data-h=id>BITINT_MAXWIDTH</h-></code>
beyond what C offers.
That is, <code><h- data-h=id>BITINT_MAXWIDTH</h-></code> may as low as 64.
I do not consider an increase of the maximum to be part of the MVP.
It's something that can always be done later, if desirable,
without any breaking changes.
</p>
<decision-block><p><intro-></intro-> 
While the proposal does not propose an increase,
some negative feedback stated that bit-precise integers as a feature
are not worth the standardization effort if they only support a width of <code><h- data-h=num>64</h-></code>.
Therefore, EWG should decide whether
an increase should take place, and, if so,
whether it should be done within this proposal.
</p></decision-block>

<p>It also should be stated that increasing the <code><h- data-h=id>BITINT_MAXWIDTH</h-></code> is not <em>really</em>
within the power of WG21 and not even within the power of compiler vendors.
</p>
<example-block><p><intro-></intro-> 
Clang supports a <code><h- data-h=id>BITINT_MAXWIDTH</h-></code> of up tp <code><h- data-h=num>8</h-><h- data-h=num_dlim>'</h-><h- data-h=num>388</h-><h- data-h=num_dlim>'</h-><h- data-h=num>608</h-></code>,
but only enables this for certain ABIs.
For example, the <a href=https://gitlab.com/x86-psABIs/x86-64-ABI>x86-64 psABI</a>
defines an ABI for any bit-precise integer width,
so the full width is available.
</p>
<p>However,
the <a href=https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md>"Basic" C ABI for WebAssembly</a>
(which Clang uses at the time of writing) has the following limitation:
</p>
<blockquote>
<p><code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-><h- data-h=sym_par>)</h-></code> types are supported up to width 128
and are represented as the smallest same-signedness Integer type with at least as many bits.
</p></blockquote>

<p>Consequently, <code><h- data-h=id>BITINT_MAXWIDTH</h-></code> is set to <code><h- data-h=num>128</h-></code> when compiling
with <tt->--target=wasm32-unknown-unknown</tt->.
</p></example-block>

<p>WG21 can define the <code><h- data-h=id>BITINT_MAXWIDTH</h-></code> as whatever they want to;
it is of no consequence because compiler vendors are not going to make that
width available when there is no platform ABI for <code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>BITINT_MAXWIDTH</h-><h- data-h=sym_par>)</h-></code>.
If compiler vendors did that,
there would be a risk of a massive future ABI break in order to comply with the system ABI,
once defined.
Without a single platform ABI, there would also be no portable way for code generated
by different compilers to interoperate,
such as compiling a C library with GCC and using it from Clang-compiled C++ code.
</p>
<p>An increase to the <code><h- data-h=id>BITINT_MAXWIDTH</h-></code> is political posturing.
That does not mean that it's entirely pointless.
If C++ defined the minimum to be, say, <code><h- data-h=num>65</h-><h- data-h=num_dlim>'</h-><h- data-h=num>535</h-></code>,
this would motivate platforms to define an ABI for large bit-precise integers.
</p>
<h4 id=possible-increased-bitint_maxwidth-values><a class=para href=#possible-increased-bitint_maxwidth-values></a>4.8.1. Possible increased <tt->BITINT_MAXWIDTH</tt-> values</h4>

<p>Firstly, it should be noted that <a href="https://wg21%2elink/p3140r0">[P3140R0]</a> got substantial criticism
just for attempting to standardize 128-bit integers for embedded developers.
As a compromise, it may be reasonable to increase the <code><h- data-h=id>BITINT_MAXWIDTH</h-></code>
only for hosted implementations, not for freestanding implementations.
That being said, there two plausible increased minimums:
</p>
<ul>
  <li>
    <code><h- data-h=num>128</h-></code>. Many platform ABIs (see example above)
    already define an ABI for <code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>128</h-><h- data-h=sym_par>)</h-></code>.
    128-bit integers have been provided by compilers for a long time now,
    at least by GCC and Clang (<code><h- data-h=kw_type>__int128</h-></code>).
    There are heaps of motivation (see <a href="https://wg21%2elink/p3140r0">[P3140R0]</a>) for 128-bit computation.
    The calling conventions are also relatively obvious for 64-bit platforms:
    pass via pair of 64-bit integers.
  </li>
  <li>
    <code><h- data-h=num>65</h-><h- data-h=num_dlim>'</h-><h- data-h=num>535</h-></code>.
    Both GCC and Clang already support this width.
    Some cryptographic use cases like future-proof RSA computations
    need 8192 bits of key size,
    and at least double that for modular arithmetic.
    It is unlikely that a cryptographic library needs 4096 bits but does not need 8192 bits
    at any point,
    but likely that 65,535 is sufficiently large, even in the next few years.
  </li>
</ul>

<p>Beyond that, <code><h- data-h=kw_type>_BitInt</h-></code> may be tricky to use.
When working with Clang's <code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>8</h-><h- data-h=num_dlim>'</h-><h- data-h=num>388</h-><h- data-h=num_dlim>'</h-><h- data-h=num>608</h-><h- data-h=sym_par>)</h-></code>,
a single <code><h- data-h=sym_op>+</h-></code> operation could result in stack overflow because the result is 1 MiB large.
The user would have to carefully ensure that all objects (including temporaries)
have static or dynamic storage duration (i.e. use <code><h- data-h=kw>new</h-></code> or global variables).
For these extreme sizes, a dynamically sized integer is more ergonomic.
Therefore, setting the minimum to millions feels unmotivated.
</p>
<h3 id=template-argument-deduction><a class=para href=#template-argument-deduction></a>4.9. Template argument deduction</h3>

<p>The following code should be valid:
</p>
<code-block><h- data-h=kw>template</h-> <h- data-h=sym_op>&lt;</h-><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>size_t</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h->
  <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>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</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=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>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>3</h-><h- data-h=sym_op>&gt;</h-><h- data-h=sym_brac>{</h-><h- data-h=sym_brac>}</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> OK, N = 3</h->
<h- data-h=sym_brac>}</h-></code-block>

<p>This would be a consequence of deduction from <code><h- data-h=kw_type>_BitInt</h-></code> being valid:
</p>
<code-block><h- data-h=kw>template</h-> <h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>unsigned</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</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>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw>template</h-> <h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>int</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw_type>void</h-> <h- data-h=id>g</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-><h- data-h=sym_par>)</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=id>f</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>3</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>(</h-><h- data-h=num>0</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, N = 3</h->
  <h- data-h=id>g</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>3</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>(</h-><h- data-h=num>0</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, N = 3</h->
<h- data-h=sym_brac>}</h-></code-block>

<p>This behavior is already implemented by Clang as a C++ compiler extension,
and makes deduction behave identically to deducing sizes of arrays.
In general, the aim is to make the deduction of <code><h- data-h=kw_type>_BitInt</h-></code> widths
as similar as possible to arrays because users are already familiar with the latter.
It is also clearly useful because it allows writing templates
that can accept <code><h- data-h=kw_type>_BitInt</h-></code> of any width.
</p>
<p>While this behavior could arguably be excluded from the MVP,
it would be extremely surprising to users if such deduction was not possible,
given that appearance of <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-></code>.
If deducing <code><h- data-h=id>N</h-></code> from <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>array</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-></code> is possible,
why would it not be possible to deduce <code><h- data-h=id>N</h-></code> from <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-></code>?
</p>
<p>One thing deliberately not allowed is:
</p><code-block><h- data-h=kw_type>_BitInt</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>123</h-><h- data-h=num_deco>wb</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>123</h-><h- data-h=num_deco>wb</h-><h- data-h=sym_punc>;</h-></code-block>

<p>This class-template-argument-deduction-like construct is not part of the MVP and if desired,
should be proposed separately.
Even if it was allowed, <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-></code> is proposed to be an alias template,
and alias templates do not support "forwarding deduction" to CTAD.
</p>
<h3 id=preprocessor><a class=para href=#preprocessor></a>4.10. No preprocessor changes, for better or worse</h3>

<p>To my understanding, no changes to the preprocessor are required.
<a href="https://open-std%2eorg/JTC1/SC22/WG14/www/docs/n2763%2epdf">[N2763]</a> did not make any changes to the C preprocessor either.
In most contexts, integer literals in the preprocessor are simply a <g-term>pp-number</g-term>,
and their numeric value or type is irrelevant.
</p>
<p>Within the controlling constant expression of an <code><h- data-h=mac>#if</h-></code> directive,
all signed and unsigned integer types
behave like <code><h- data-h=id_type>intmax_t</h-></code> and <code><h- data-h=id_type>uintmax_t</h-></code> (<a href=https://eel.is/c++draft/cpp.cond>[cpp.cond]</a>),
which may be surprising.
</p>
<example-block><p><intro-></intro-> 
The following code is ill-formed
if <code><h- data-h=id_type>intmax_t</h-></code> is a 64-bit signed integer (which it is on many platforms):
</p><code-block><h- data-h=mac>#if </h-><h- data-h=num>1</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_deco>wb</h-><h- data-h=mac> </h-><h- data-h=cmt_dlim>//</h-><h- data-h=cmt> error</h->
<h- data-h=mac>#endif</h->
<h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>81</h-><h- data-h=sym_par>)</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>1</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_deco>wb</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> OK</h-></code-block>
<p><code><h- data-h=mac>#if </h-><h- data-h=num>1</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_dlim>'</h-><h- data-h=num>000</h-><h- data-h=num_deco>wb</h-></code> is ill-formed
because the integer literal is of type <code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>81</h-><h- data-h=sym_par>)</h-></code>,
which behaves like <code><h- data-h=id_type>intmax_t</h-></code> within <code><h- data-h=mac>#if</h-></code>.
Since <math display=inline><msup><mn>10</mn><mn>32</mn></msup></math> does not fit within <code><h- data-h=id_type>intmax_t</h-></code>,
the literal is ill-formed (<a href=https://eel.is/c++draft/lex.icon#4>[lex.icon] paragraph 4</a>).
</p></example-block>

<p>The current behavior could be seen as suboptimal
because it makes bit-precise integers dysfunctional within the preprocessor.
However, the preprocessor is largely "owned" by C,
and any fix should go through WG14.
In any case, fixing the C preprocessor is not part of the MVP.
</p>

<h2 id=library-design><a class=para href=#library-design></a>5. Library design</h2>

<p>When discussing library design,
it is important to understand that the vast majority of support for bit-precise integers
"sneaks" into the standard without any explicit design changes or wording changes.
Many existing facilities (e.g. <code><h- data-h=str>&lt;bit&gt;</h-></code>) support any integer type;
adding bit-precise integers to the core language silently adds library support.
The following sections deal mostly with areas of the standard
where some explicit design changes must be made.
</p>
<note-block><p><intro-></intro-> 
See <a href=#impact-on-the-standard-library>§8.2. Impact on the standard library</a>
for a complete list of changes,
including such silently added support.
</p></note-block>

<h3 id=naming-of-the-alias-template><a class=para href=#naming-of-the-alias-template></a>5.1. Naming of the alias template</h3>

<p>The approach is to expose bit-precise integers via two alias templates:
</p>
<code-block><h- data-h=kw>template</h-> <h- data-h=sym_op>&lt;</h-><h- data-h=id_type>size_t</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>using</h-> <h- data-h=id>bit_int</h-> <h- data-h=sym_op>=</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw>template</h-> <h- data-h=sym_op>&lt;</h-><h- data-h=id_type>size_t</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>using</h-> <h- data-h=id>bit_uint</h-> <h- data-h=sym_op>=</h-> <h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<p>The goal is to have a spelling reminiscent of the C <code><h- data-h=kw_type>_BitInt</h-></code> spelling.
There are no clear problems with it,
so it is the obvious candidate.
<tt->int</tt-> and <tt->uint</tt-> match the naming scheme of existing aliases,
such as <code><h- data-h=id_type>intN_t</h-></code>, <code><h- data-h=id_type>uint_fastN_t</h-></code>, etc.
</p>
<p>The alias names as a whole also act as abbreviations of the core language term
(which is copied from C):
</p><ul>
  <li><code><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-></code> is a bit-precise signed integer of width <code><h- data-h=id>N</h-></code></li>
  <li><code><h- data-h=id>bit_uint</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-></code> is a bit-precise unsigned integer of width <code><h- data-h=id>N</h-></code></li>
</ul>

<h4 id=why-no-_t-suffix><a class=para href=#why-no-_t-suffix></a>5.1.1. Why no <code><h- data-h=id_type>_t</h-></code> suffix?</h4>

<p>While the <code><h- data-h=id_type>_t</h-></code> suffix would be conventional for simple type aliases
such as <code><h- data-h=id_type>uint32_t</h-></code>,
there is no clear precedent for alias templates.
There are alias templates such as <code><h- data-h=id>expected</h-><h- data-h=sym_op>::</h-><h- data-h=id>rebind</h-></code>
without any <code><h- data-h=id_type>_t</h-></code> or <code><h- data-h=id>_type</h-></code> suffix,
but "type trait wrappers" such as <code><h- data-h=id_type>conditional_t</h-></code> which have a <code><h- data-h=id_type>_t</h-></code> suffix.
</p>
<p>The <code><h- data-h=id_type>_t</h-></code> suffix does not add any clear benefit,
adds verbosity,
and distances the name from the C spelling <code><h- data-h=kw_type>_BitInt</h-></code>.
Brevity is important here because <code><h- data-h=id>bit_int</h-></code>
is expected to be a commonly spelled type.
A function doing some bit manipulation could use this name numerous times.
</p>
<h3 id=printing-support><a class=para href=#printing-support></a>5.2. <tt->format</tt->, <tt->to_chars</tt->, and <tt->to_string</tt-> support for bit-precise integers</h3>

<p>I consider printing support to be part of the MVP for bit-precise integers.
There are numerous reasons for this:
</p>
<ul>
  <li>
    Being able to print bit-precise integers is clearly useful.
    It seems unthinkable that it would not be supported at some point,
    even if support was not added by this proposal.
  </li>
  <li>
    It would take considerable wording effort to exclude
    support for bit-precise integers from these facilities,
    only for it to be reverted once support is inevitably added.
    For example, the expression <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>println</h-><h- data-h=sym_par>(</h-><h- data-h=str_dlim>"</h-><h- data-h=str>{:b}</h-><h- data-h=str_dlim>"</h-><h- data-h=sym_punc>,</h-> <h- data-h=num>100</h-><h- data-h=sym_par>)</h-></code> prints <tt->1100100</tt->.
    This is specified in terms of <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>to_chars</h-></code> where <code><h- data-h=id>base</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>2</h-></code>.
    If <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>to_chars</h-></code> does not actually support bit-precise integers,
    this wording becomes nonsensical.
  </li>
  <li>
    The design is obvious.
    No changes to <code><h- data-h=id>format</h-></code> are necessary
    if <code><h- data-h=id>to_chars</h-></code> supports bit-precise integers.
  </li>
</ul>

<p>To facilitate printing and parsing,
the following function templates are added:
</p>
<code-block><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>to_chars_result</h-> <h- data-h=id>to_chars</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>first</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>last</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>value</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>base</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>10</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>from_chars_result</h-> <h- data-h=id>from_chars</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>first</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>last</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&amp;</h-> <h- data-h=id>value</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>base</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>10</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->

<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<note-block><p><intro-></intro-> 
The <code><h- data-h=id>to_string</h-></code> and <code><h- data-h=id>to_wstring</h-></code> overloads for integral types
are made <code><h- data-h=kw>constexpr</h-></code> by <a href="https://wg21%2elink/p3438r0">[P3438R0]</a>.
If that paper be accepted,
the overloads for bit-precise integers should also be made <code><h- data-h=kw>constexpr</h-></code> for consistency.
</p></note-block>

<note-block><p><intro-></intro-> 
See also <a href=#passing-bitint>§5.13. Passing <tt->bit_int</tt-> into standard library function templates</a> for an explanation of why this function passes by value.
</p></note-block>

<p><code><h- data-h=id>T</h-></code> is constrained to accept any bit-precise integer type.
It would have also been possible to accept two overloads
taking <code><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-></code> and <code><h- data-h=id>bit_uint</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-></code> with some constant template argument instead,
but this doubles the amount of declarations without any clear benefit.
</p>
<p>Such a signature is also more future-proof:
the constraints can be relaxed if more types are supported (e.g. extended integer types),
whereas a <code><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-></code> parameter can only support bit-precise integer,
until the end of times.
For parsing and printing, this seems short-sighted.
</p>
<p>It should also be noted that the existing overloads such as <code><h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-><h- data-h=sym_par>)</h-></code>
cannot be removed because it would break existing code.
</p>
<example-block><p><intro-></intro-> 
Wrapper types which are convertible to <code><h- data-h=kw_type>int</h-></code> (but are not <code><h- data-h=kw_type>int</h-></code>)
may rely on these dedicated overloads:
</p><code-block><h- data-h=kw>struct</h-> <h- data-h=id>int_wrapper</h-> <h- data-h=sym_brac>{</h->
  <h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>operator</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=sym_par>)</h-> <h- data-h=kw>const</h-> <h- data-h=sym_brac>{</h-> <h- data-h=kw_ctrl>return</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>;</h-> <h- data-h=sym_brac>}</h->
<h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->

<h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>string</h-> <h- data-h=id>to_string_generic</h-><h- data-h=sym_par>(</h-><h- data-h=id>integral</h-> <h- data-h=kw>auto</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->

<h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=id>int_wrapper</h-><h- data-h=sym_brac>{</h-><h- data-h=sym_brac>}</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->
<h- data-h=id>to_string_generic</h-><h- data-h=sym_par>(</h-><h- data-h=id>int_wrapper</h-><h- data-h=sym_brac>{</h-><h- data-h=sym_brac>}</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> error: integral&lt;int_wrapper&gt; constraint not satisfied</h-></code-block>

<p>Analogously, if we replaced all the non-template overloads
and handled all integers in a single function template,
this may break existing valid calls to <code><h- data-h=id>to_string</h-></code> etc.
</p></example-block>

<h3 id=preventing-iota-view-abi-break><a class=para href=#preventing-iota-view-abi-break></a>5.3. Preventing <tt->ranges::iota_view</tt-> ABI break</h3>

<p>Due to the current wording in <a href=https://eel.is/c++draft/range.iota.view#1>[range.iota.view] paragraph 1</a>,
adding bit-precise integers or extended integers of greater width than <code><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-></code>
potentially forces the implementation to redefine
<code><h- data-h=id>ranges</h-><h- data-h=sym_op>::</h-><h- data-h=id>iota_view</h-><h- data-h=sym_op>::</h-><h- data-h=id>iterator</h-><h- data-h=sym_op>::</h-><h- data-h=id>difference_type</h-></code>.
Changing the type would be an ABI break.
This problem is similar to historical issues with <code><h- data-h=id_type>intmax_t</h-></code>,
where adding 128-bit integers would force the implementation to redefine the former type.
</p>
<p>To prevent this, the proposal tweaks the wording in <a href=#range.iota.view>§ [range.iota.view]</a>
so that new extended or bit-precise integers may be added.
Dealing with extended integer types extends slightly beyond the scope of the MVP,
but it would be silly to leave the wording in an undesirable state,
where adding a 128-bit extended integer still forces an ABI break.
</p>
<h3 id=bit-precise-size_t-ptrdiff_t><a class=para href=#bit-precise-size_t-ptrdiff_t></a>5.4. Bit-precise <code><h- data-h=id_type>size_t</h-></code>, <code><h- data-h=id_type>ptrdiff_t</h-></code></h3>

<p>As in C,
the proposal allows for <code><h- data-h=id_type>size_t</h-></code> and <code><h- data-h=id_type>ptrdiff_t</h-></code> to be bit-precise integers,
which is a consequence of <code><h- data-h=kw>sizeof</h-></code> and pointer subtraction
potentially yielding a bit-precise integer.
</p>
<p>Whether bit-precise integers in those places is desirable is for implementers and users to decide,
but from the perspective of the C standard and the C++ standard,
there is no compelling reason to disallow it.
It would be a massive breaking change if existing C++ implementations redefined
the type of these,
so it is unlikely we will see an implementation that makes use of this freedom anytime soon.
</p>
<h3 id=bitint-abs><a class=para href=#bitint-abs></a>5.5. New <tt->abs</tt-> overload</h3>

<p>The proposal adds the following <code><h- data-h=id>abs</h-></code> overload:
</p>
<code-block><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id_type>size_t</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>j</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<p>While <code><h- data-h=id>abs</h-></code> is not strictly part of the MVP,
taking the absolute of an integer is such a fundamental, easy-to-implement, and useful
operation that we may as well include it here.
</p>
<note-block><p><intro-></intro-> 
See <a href=#passing-bitint>§5.13. Passing <tt->bit_int</tt-> into standard library function templates</a> for an explanation as to why this signature is chosen.
</p></note-block>

<h3 id=bitint-cmath><a class=para href=#bitint-cmath></a>5.6. Using bit-precise integers in <tt->&lt;cmath&gt;</tt-> functions</h3>

<p>The proposal adds support for using bit-precise integers in all <tt->&lt;cmath&gt;</tt-> functions:
</p>
<code-block><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>sqrt</h-><h- data-h=sym_par>(</h-><h- data-h=num>0</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->    <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> OK, int → call to std::sqrt(double)</h->
<h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>sqrt</h-><h- data-h=sym_par>(</h-><h- data-h=num>0</h-><h- data-h=num_deco>wb</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> OK, _BitInt(1) → call to std::sqrt(double)</h-></code-block>

<p>This is done simply for consistency with C:
after some consulting with WG14 members,
I am under the impression that C's <code><h- data-h=str>&lt;tgmath.h&gt;</h-></code> functions deliberately
all integers types (including bit-precise integers),
not just as the result of defective wording.
Consequently, <code><h- data-h=kw_type>_BitInt</h-></code> can be passed both to
the type-generic <code><h- data-h=mac>sqrt</h-></code> macro
as well as to the regular <code><h- data-h=id>sqrt</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>double</h-><h- data-h=sym_par>)</h-></code> function.
</p>
<h3 id=random-support><a class=para href=#random-support></a>5.7. Lack of random number generation support</h3>

<p>Support for random number generation is not added
because too many design changes are required,
with non-obvious decisions.
Users can also live without bit-precise integer support in <code><h- data-h=str>&lt;random&gt;</h-></code>
for a while, so this feature is not part of the MVP.
</p>
<p>Wording changes would be needed because <code><h- data-h=str>&lt;random&gt;</h-></code>
specifically supports certain integer types specified in <a href=https://eel.is/c++draft/rand.req.genl>[rand.req.genl]</a>,
rather than having blanket support for bit-precise integers.
</p>
<p>Another issue lies with <code><h- data-h=id>linear_congruential_engine</h-></code>.
This generator performs modular arithmetic,
which requires double the integer width for intermediate results.
For example, <code><h- data-h=id_type>int64_t</h-></code> modular arithmetic is implemented using <code><h- data-h=kw_type>__int128</h-></code>
in some standard libraries (if available).
An obvious problem for bit-precise integers is how modular arithmetic
for <code><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>BITINT_MAXWIDTH</h-><h- data-h=sym_op>&gt;</h-></code> is meant to be implemented.
We obviously can't just use a wider integer type because none exists.
These and other potential design issues should be explored in a separate paper.
</p>
<h3 id=simd-support><a class=para href=#simd-support></a>5.8. <tt->simd</tt-> support for bit-precise integers</h3>

<p><code><h- data-h=str>&lt;simd&gt;</h-></code> is one of the few parts in the standard library
where the implementation is highly specific to integer widths,
at least if high implementation quality is needed.
</p>
<h4 id=simd-design-problems><a class=para href=#simd-design-problems></a>5.8.1. <tt->simd</tt-> design problems</h4>

<p>There are many important questions, such as:
</p>
<ul>
  <li>
    How do we best optimize <code><h- data-h=id>simd</h-><h- data-h=sym_op>::</h-><h- data-h=id>vec</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>1</h-><h- data-h=sym_op>&gt;&gt;</h-></code>?
    that type is effectively a bitset.
  </li>
  <li>
    How do we deal with padding bits?
    Standard integers are typically padding-free, but bit-precise integers are not
    except for specific sizes.
  </li>
  <li>
    What about <code><h- data-h=id>simd</h-><h- data-h=sym_op>::</h-><h- data-h=id>vec</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>512</h-><h- data-h=sym_op>&gt;&gt;</h-></code> or even greater widths?
    It seems like this case degenerates into a scalar implementation anyway.
  </li>
</ul>

<p>It is not obvious whether design changes are needed to properly
support bit-precise integers.
Furthermore, adding a naive implementation for e.g. <code><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>1</h-><h- data-h=sym_op>&gt;</h-></code>
would result in an ABI break when being replaced with a more efficient "bit-packed"
implementation later.
</p>
<h4 id=simd-design-conclusion><a class=para href=#simd-design-conclusion></a>5.8.2. <tt->simd</tt-> design conclusion</h4>

<p>Due to these design concerns,
I do not consider <em>full</em><code><h- data-h=id>simd</h-></code> support to be part of the MVP.
However, <code><h- data-h=id>simd</h-></code> support for bit-precise integers is clearly useful,
so a compromise is possible:
<code><h- data-h=id>simd</h-></code> support is added only for those bit-precise integers
whose width matches a standard integer type.
</p>
<p>This means that a <code><h- data-h=id>simd</h-><h- data-h=sym_op>::</h-><h- data-h=id>vec</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>32</h-><h- data-h=sym_op>&gt;&gt;</h-></code> implementation
"piggy-backs" off of an existing <code><h- data-h=id>simd</h-><h- data-h=sym_op>::</h-><h- data-h=id>vec</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>int</h-><h- data-h=sym_op>&gt;</h-></code> implementation,
assuming <code><h- data-h=kw_type>int</h-></code> is a 32-bit signed integer.
Such limited support is easy to provide.
</p>
<note-block><p><intro-></intro-> 
This restriction is inspired by the constraints (inherited from C) on
<code><h- data-h=id>stdc_count_ones</h-></code> and other <code><h- data-h=str>&lt;stdbit.h&gt;</h-></code> functions.
Those functions accept standard integers
as well as bit-precise integers of matching width.
</p></note-block>

<h3 id=valarray-support><a class=para href=#valarray-support></a>5.9. <tt->valarray</tt-> support for bit-precise integers</h3>

<p>Bit-precise integer support in <code><h- data-h=id>valarray</h-></code> is required.
While the same concerns as with <code><h- data-h=str>&lt;simd&gt;</h-></code> apply <em>in theory</em>,
it is easy to provide a naive implementation,
and the implementation in standard libraries is typically naive anyway,
including for existing integers.
</p>
<note-block><p><intro-></intro-> 
Naive means that in libc++, libstdc++, and the MSVC STL,
operator overloads such as <code><h- data-h=id>valarray</h-><h- data-h=sym_op>::</h-><h- data-h=kw>operator</h-><h- data-h=sym_op>+</h-></code>
are implemented as a simple loop
rather than being manually optimized with SIMD operations.
</p></note-block>

<h3 id=broadening-type-traits><a class=para href=#broadening-type-traits></a>5.10. Broadening <tt->is_integral</tt-></h3>

<p>Since bit-precise integer types are integral types,
obviously, <code><h- data-h=id>is_integral_v</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-></code> should be <code><h- data-h=bool>true</h-></code> for any bit-precise integer <code><h- data-h=id>T</h-></code>.
</p>
<p>There is a potential concern that existing C++ code constrained using
<code><h- data-h=id>is_integral</h-></code> or <code><h- data-h=id>integral</h-></code> never anticipated that the templates
would be instantiated with huge integers like <code><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>1024</h-><h- data-h=sym_op>&gt;</h-></code>.
That is simply a problem we have to live with.
The only way to avoid the issue would be to create a taxonomy of integer types
that is confusing and inconsistent with C
(e.g. by not considering bit-precise integers to be integral types),
or to make <code><h- data-h=id>is_integral_v</h-></code> inconsistent with the term "integral type".
Both of these alternatives seem terrible.
</p>
<h3 id=misc-support><a class=para href=#misc-support></a>5.11. Miscellaneous library support</h3>

<p>There are many more standard library parts to which support for bit-precise integers is added.
Examples include:
</p>
<ul>
  <li>
    C headers such as <code><h- data-h=str>&lt;stdbit.h&gt;</h-></code> and <code><h- data-h=str>&lt;stdckdint.h&gt;</h-></code>
    receive the same degree of support as they have in C.
    This is the obvious design, and any deviation would need to be justified somehow.
  </li>
  <li>
    Various utilities such as <code><h- data-h=id>to_integer</h-></code> and <code><h- data-h=id>hash</h-></code>
    receive support for bit-precise integers.
    It is implausible that support wouldn't be added in the long run,
    and the support is added by extending the existing blanket support for integers;
    no wording changes are needed.
  </li>
</ul>

<h3 id=feature-testing><a class=para href=#feature-testing></a>5.12. Feature testing</h3>

<p>After consulting with some LWG and SG10 experts,
I have opted to add only two feature-test macros:
one for the core feature,
and one for the standard library.
While more granular feature-testing could be useful considering
that the feature is quite large,
there seems to be little enthusiasm for it.
</p>
<h3 id=passing-bitint><a class=para href=#passing-bitint></a>5.13. Passing <tt->bit_int</tt-> into standard library function templates</h3>

<p>Unlike standard integers,
it is plausible that some bit-precise integers are too large to be passed on the stack,
or at least too large to make this the "default option".
Nonetheless,
all proposed library functions which operate on <code><h- data-h=id>bit_int</h-></code>
should accept <code><h- data-h=id>bit_int</h-></code> by value.
</p>
<example-block><p><intro-></intro-> 
The proposal adds this <code><h- data-h=id>abs</h-></code> overload:
</p><code-block><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id_type>size_t</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>j</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<p>If implemented verbatim like this,
in the <a href=https://gitlab.com/x86-psABIs/x86-64-ABI>x86-64 psABI</a>,
<code><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>64</h-><h- data-h=sym_op>&gt;</h-></code> would be passed via single register,
<code><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>128</h-><h- data-h=sym_op>&gt;</h-></code> would be passed via a pair of registers,
and any wider integer integer would be pushed onto the stack.
Passing via stack is questionable and may result in an immediate program crash
when millions of bits are involved.
</p></example-block>

<p>The reason for having such signatures
is that the details of how values are passed into functions
are outside the scope of the standard.
Since most functions in the standard are not addressable,
and since we don't care about keeping the results of reflecting on the standard library stable,
the actual overload sets in the library implementation can differ from the declarations
in the standard.
</p>
<example-block><p><intro-></intro-> 
An implementation of the <code><h- data-h=id>abs</h-></code> function template could look as follows:
</p>
<code-block><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id_type>size_t</h-> <h- data-h=id>__n</h-><h- data-h=sym_op>&gt;</h->
<h- data-h=kw>constexpr</h-> <h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>__n</h-><h- data-h=sym_par>)</h-> <h- data-h=id>__j</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> pass small integers by value</h->
  <h- data-h=kw_ctrl>return</h-> <h- data-h=id>__j</h-> <h- data-h=sym_op>&gt;=</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>?</h-> <h- data-h=id>__j</h-> <h- data-h=sym_punc>:</h-> <h- data-h=sym_op>-</h-><h- data-h=id>__j</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id_type>size_t</h-> <h- data-h=id>__n</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>requires</h-> <h- data-h=sym_par>(</h-><h- data-h=kw>sizeof</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>__n</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&gt;</h-> <h- data-h=id>__pass_by_value_max_size</h-><h- data-h=sym_par>)</h->
<h- data-h=kw>constexpr</h-> <h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=kw>const</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>__n</h-><h- data-h=sym_par>)</h-><h- data-h=sym_op>&amp;</h-> <h- data-h=id>__j</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> pass large integers by reference</h->
  <h- data-h=kw_ctrl>return</h-> <h- data-h=id>__j</h-> <h- data-h=sym_op>&gt;=</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>?</h-> <h- data-h=id>__j</h-> <h- data-h=sym_punc>:</h-> <h- data-h=sym_op>-</h-><h- data-h=id>__j</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-></code-block>

<p>Another plausible implementation strategy is to
use an ABI-altering, implementation-specific attribute.
</p><code-block><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id_type>size_t</h-> <h- data-h=id>__n</h-><h- data-h=sym_op>&gt;</h->
<h- data-h=kw>constexpr</h-> <h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=sym_sqr>[</h-><h- data-h=sym_sqr>[</h-><h- data-h=id>impl</h-><h- data-h=sym_op>::</h-><h- data-h=id>pass_large_by_ref</h-><h- data-h=sym_sqr>]</h-><h- data-h=sym_sqr>]</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>__n</h-><h- data-h=sym_par>)</h-> <h- data-h=id>__j</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
  <h- data-h=kw_ctrl>return</h-> <h- data-h=id>__j</h-> <h- data-h=sym_op>&gt;=</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>?</h-> <h- data-h=id>__j</h-> <h- data-h=sym_punc>:</h-> <h- data-h=sym_op>-</h-><h- data-h=id>__j</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-></code-block>
<p>Such an attribute could alter the ABI for <code><h- data-h=id>__j</h-></code>
so that it is passed indirectly (via address) beyond a certain size,
not on the stack.
</p></example-block>

<p>Admittedly, having the standard pass all integers by value may give the user
the false impression that a <code><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-></code> function parameter (with unconstrained <code><h- data-h=id>N</h-></code>)
is idiomatic and harmless, which is problematic.
However, it is seemingly the lesser evil,
since the alternative is wasting LEWG and LWG time on quality of implementation.
</p>

<h2 id=education><a class=para href=#education></a>6. Education</h2>

<p>Following SG20 Education recommendations at Sofia 2025,
this proposal contains guidance on how bit-precise integers
are meant to be taught by learning resources.
</p>
<h3 id=teaching-principles><a class=para href=#teaching-principles></a>6.1. Teaching principles</h3>

<ol>
  <li>
    Emphasize familiar features.
    The closest equivalents to <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-></code> and <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_uint</h-></code>
    are <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>intN_t</h-></code> and <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>uintN_t</h-></code>, respectively.
  </li>
  <li>
    Clearly distinguish <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-></code> from other existing integer types.
    It should be clarified that <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-></code> is always a distinct type
    from the <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>intN_t</h-></code> aliases, even if it behaves similarly.
    Furthermore, the major differences are:
    <ul>
      <li>
        <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-></code> is not optional (though there exists a maximum width),
        whereas any <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>intN_t</h-></code> may not actually exist.
      </li>
      <li>
        <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-></code> is not subject to integer promotion,
        unlike any of the existing standard integer types.
      </li>
      <li>
        <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-></code> cannot be used as the underlying type of enumerations.
      </li>
    </ul>
  </li>
  <li>
    Only reference the <code><h- data-h=kw_type>_BitInt</h-></code> spelling in a note on C compatibility.
    <code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-><h- data-h=sym_par>)</h-></code> looks nothing like the class templates that C++ users are used to,
    and nothing suggests that <code><h- data-h=id>N</h-></code> is required to be a constant expression.
    The <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-></code> and <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_uint</h-></code> alias templates
    should be taught first and foremost.
  </li>
  <li>
    Point out potential pitfalls:
    <ul>
      <li>
        <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-></code> has a <code><h- data-h=id>BITINT_MAXWIDTH</h-></code> which is not guaranteed
        to be any more than <code><h- data-h=num>64</h-></code>.
        The user should be made aware of this portability problem.
      </li>
      <li>
        When writing generic code,
        the user should be made aware that accepting <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-></code>
        in a function signature may be problematic.
        For all they know, <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-></code> could have millions of bits,
        and this could make the type too large for passing on the stack.
      </li>
    </ul>
  </li>
</ol>


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

<p><code><h- data-h=kw_type>_BitInt</h-></code>, formerly known as <code><h- data-h=id>_ExtInt</h-></code>, has been a compiler extension
in Clang for several years now.
The core language changes are essentially standardizing that compiler extension.
</p>

<h2 id=impact-on-the-standard><a class=para href=#impact-on-the-standard></a>8. Impact on the standard</h2>

<h3 id=impact-on-the-core-language><a class=para href=#impact-on-the-core-language></a>8.1. Impact on the core language</h3>

<p>The core language changes essentially boil down to adding the <code><h- data-h=kw_type>_BitInt</h-></code>
type and the <code><h- data-h=id>wb</h-></code> <g-term>integer-suffix</g-term>.
This obviously comes with various syntax changes,
definitions of conversion rank,
addition of template argument deduction rules, etc.
The vast majority of core language wording which deals with integers
is not affected by the existence of bit-precise integers.
</p>
<h3 id=impact-on-the-standard-library><a class=para href=#impact-on-the-standard-library></a>8.2. Impact on the standard library</h3>

<p>The impact of adding bit-precise integers to the standard library is quite enormous
because there are many parts of the library
which already support any integer type via blanket wording.
Additionally, bit-precise integer support for various components such as <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>to_chars</h-></code>
is explicitly added.
</p>
<p>Since this proposal does not explicitly remove support for bit-precise integers,
support "sneaks" its way in, without any explicit wording changes.
For example, use of bit-precise integers in <code><h- data-h=str>&lt;simd&gt;</h-></code>, <code><h- data-h=str>&lt;bit&gt;</h-></code>, <code><h- data-h=str>&lt;valarray&gt;</h-></code>,
and many others is enabled.
</p>
<p>The addition of bit-precise integers means that (as in the core language),
the <code><h- data-h=id>size_type</h-></code> of various containers may be a bit-precise integer,
<code><h- data-h=id_type>size_t</h-></code> and <code><h- data-h=id_type>ptrdiff_t</h-></code> may be bit-precise integers, etc.
</p>
<p>Find a summary of affected library components below.
In the interest of reducing noise,
the possible changes to container <code><h- data-h=id>size_type</h-></code>s are not listed.
</p>
<table class=wording>
  <tr>
    <th>Header</th>
    <th>Changes</th>
    <th>Wording</th>
    <th>See also</th>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;algorithm&gt;</h-></code></td>
    <td>Relax some <i>Mandates</i> due to implementability problems.</td>
    <td><a href=#alg.foreach>§ [alg.foreach]</a></td>
    <td><a href=#misc-support>§5.11. Miscellaneous library support</a></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;atomic&gt;</h-></code></td>
    <td>
      Add support for bit-precise integers.
      Partial specializations for integral types also support <code><h- data-h=id>bit_int</h-></code>.
    </td>
    <td><a href=#atomics.ref.int>§ [atomics.ref.int]</a>,<br/><a href=#atomics.types.int>§ [atomics.types.int]</a></td>
    <td><a href=#misc-support>§5.11. Miscellaneous library support</a></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;bit&gt;</h-></code></td>
    <td>Expand blanket support for integers.</td>
    <td>None required</td>
    <td><a href=#misc-support>§5.11. Miscellaneous library support</a></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;charconv&gt;</h-></code></td>
    <td>Add <code><h- data-h=id>to_chars</h-></code> and <code><h- data-h=id>from_chars</h-></code> overloads.</td>
    <td><a href=#charconv.syn>§ [charconv.syn]</a></td>
    <td><a href=#printing-support>§5.2. <tt->format</tt->, <tt->to_chars</tt->, and <tt->to_string</tt-> support for bit-precise integers</a></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;chrono&gt;</h-></code></td>
    <td>Bit-precise integers can be used in e.g. <code><h- data-h=id>duration</h-></code>.</td>
    <td>None required</td>
    <td></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;climits&gt;</h-></code></td>
    <td>Add <code><h- data-h=id>BITINT_MAXWIDTH</h-></code> macro.</td>
    <td><a href=#climits.syn>§ [climits.syn]</a></td>
    <td></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;cmath&gt;</h-></code></td>
    <td>
      Add <code><h- data-h=id>abs</h-></code> overload.
      Allow passing bit-precise integers to most math functions.
    </td>
    <td><a href=#cmath.syn>§ [cmath.syn]</a></td>
    <td><a href=#bitint-abs>§5.5. New <tt->abs</tt-> overload</a>,<br/><a href=#bitint-cmath>§5.6. Using bit-precise integers in <tt->&lt;cmath&gt;</tt-> functions</a></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;complex&gt;</h-></code></td>
    <td>Expand blanket support for integers.</td>
    <td>None required</td>
    <td><a href=#misc-support>§5.11. Miscellaneous library support</a></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;concepts&gt;</h-></code></td>
    <td>Some concepts broadened (e.g. <code><h- data-h=id>integral</h-></code>).</td>
    <td>None required</td>
    <td><a href=#broadening-type-traits>§5.10. Broadening <tt->is_integral</tt-></a></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;format&gt;</h-></code></td>
    <td>Expand blanket support for integers.</td>
    <td>None required</td>
    <td><a href=#printing-support>§5.2. <tt->format</tt->, <tt->to_chars</tt->, and <tt->to_string</tt-> support for bit-precise integers</a></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;limits&gt;</h-></code></td>
    <td><code><h- data-h=id>numeric_limits</h-></code> specializations required as blanket support.</td>
    <td>None required</td>
    <td></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;limits.h&gt;</h-></code></td>
    <td>Changed indirectly.</td>
    <td><a href=#climits.syn>§ [climits.syn]</a></td>
    <td><code><h- data-h=str>&lt;climits&gt;</h-></code></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;linalg&gt;</h-></code></td>
    <td>Expand blanket support for integers.</td>
    <td>None required</td>
    <td></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;mdspan&gt;</h-></code></td>
    <td>Bit-precise integers may be used as an index type.</td>
    <td>None required</td>
    <td></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;meta&gt;</h-></code></td>
    <td>Some queries broadened (e.g. <code><h- data-h=id>is_integral_type</h-></code>).</td>
    <td>None required</td>
    <td><a href=#broadening-type-traits>§5.10. Broadening <tt->is_integral</tt-></a></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;numeric&gt;</h-></code></td>
    <td>Expand blanket support for integers (<code><h- data-h=id>gcd</h-></code>, saturating arithmetic, etc.)</td>
    <td>None required</td>
    <td></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;ranges&gt;</h-></code></td>
    <td>
      Change <code><i><h- data-h=id>IOTA-DIFF-T</h-></i></code> to prevent ABI break
      when integer types are added.
    </td>
    <td><a href=#range.iota.view>§ [range.iota.view]</a></td>
    <td><a href=#preventing-iota-view-abi-break>§5.3. Preventing <tt->ranges::iota_view</tt-> ABI break</a></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;simd&gt;</h-></code></td>
    <td>Add limited support for bit-precise integers.</td>
    <td><a href=#simd.general>§ [simd.general]</a></td>
    <td><a href=#simd-support>§5.8. <tt->simd</tt-> support for bit-precise integers</a></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;stdbit.h&gt;</h-></code></td>
    <td>Inherit bit-precise integer support from C.</td>
    <td><a href=#stdbit.h.syn>§ [stdbit.h.syn]</a></td>
    <td><a href=#misc-support>§5.11. Miscellaneous library support</a></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;stdckdint.h&gt;</h-></code></td>
    <td>Inherit bit-precise integer support from C.</td>
    <td><a href=#numerics.c.ckdint>§ [numerics.c.ckdint]</a></td>
    <td><a href=#misc-support>§5.11. Miscellaneous library support</a></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;string&gt;</h-></code></td>
    <td>Add <code><h- data-h=id>to_string</h-></code> and <code><h- data-h=id>to_wstring</h-></code> overloads.</td>
    <td><a href=#string.conversions>§ [string.conversions]</a></td>
    <td><a href=#printing-support>§5.2. <tt->format</tt->, <tt->to_chars</tt->, and <tt->to_string</tt-> support for bit-precise integers</a></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;tgmath.h&gt;</h-></code></td>
    <td>Changed indirectly.</td>
    <td>None required</td>
    <td><code><h- data-h=str>&lt;cmath&gt;</h-></code>, <code><h- data-h=str>&lt;complex&gt;</h-></code></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;type_traits&gt;</h-></code></td>
    <td>Some traits broadened (e.g. <code><h- data-h=id>is_integral</h-></code>).</td>
    <td>None required</td>
    <td><a href=#broadening-type-traits>§5.10. Broadening <tt->is_integral</tt-></a></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;utility&gt;</h-></code></td>
    <td>Expand blanket support for integers (e.g. <code><h- data-h=id>to_integer</h-></code>).</td>
    <td>None required</td>
    <td><a href=#misc-support>§5.11. Miscellaneous library support</a></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;valarray&gt;</h-></code></td>
    <td>Expand blanket support for integers.</td>
    <td>None required</td>
    <td><a href=#valarray-support>§5.9. <tt->valarray</tt-> support for bit-precise integers</a></td>
  </tr>
  <tr>
    <td><code><h- data-h=str>&lt;version&gt;</h-></code></td>
    <td>Add feature-test macros.</td>
    <td><a href=#version.syn>§ [version.syn]</a></td>
    <td></td>
  </tr>
</table>

<note-block><p><intro-></intro-> 
There are numerous other standard library facilities which now support bit-precise integers,
but are not mentioned specially because they are not numeric in nature.
For example, it is possible to store a <code><h- data-h=id>bit_int</h-></code> in <code><h- data-h=id>any</h-></code>,
but <code><h- data-h=str>&lt;any&gt;</h-></code> is not mentioned specially in the table above.
</p></note-block>

<note-block><p><intro-></intro-> 
See <a href=https://eel.is/c++draft/headers>[headers]</a> and <a href=https://eel.is/c++draft/support.c.headers.general>[support.c.headers.general]</a>
for a complete list of headers.
</p></note-block>


<h2 id=wording><a class=para href=#wording></a>9. Wording</h2>

<p>The following changes are relative to <a href="https://wg21%2elink/n5014">[N5014]</a>.
</p>

<h3 id=core><a class=para href=#core></a>9.1. Core</h3>

<style>
  math[display=inline] {
    font-size: inherit;
  }

  .wording td {
    vertical-align: top;
    border-bottom: 1px solid var(--border-color);
  }

  table.wording code-block {
    margin: 0;
  }
</style>





<decision-block><p><intro-></intro-> 
CWG needs to decide what the <q>quoted</q> (prose)
spelling of bit-precise integer types should be.
The current spelling is e.g. “<code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-></code> of width <math display=inline><mi>N</mi></math>”,
which is fairly similar to other code-heavy spellings like <q><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>int</h-></code></q>.
</p>
<p>However, this is questionable because <code><h- data-h=kw_type>_BitInt</h-></code> is not valid C++ in itself;
<code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-><h- data-h=sym_par>)</h-></code> is.
An alternative would be a pure prose spelling, like
<q>bit-precise unsigned integer of width <math display=inline><mi>N</mi></math></q>,
which is a bit more verbose.
</p>
<p>There is no strong author preference.
</p></decision-block>

<h4 id=lex.icon><a class=para href=#lex%2eicon></a>[lex.icon]</h4>

<p>In <a href=https://eel.is/c++draft/lex.icon>[lex.icon]</a>,
change the grammar as follows:
</p>
<diff-block>
<dl class=grammar>
  <dt><g-term>integer-suffix</g-term>:</dt>
  <dd>unsigned-suffix long-suffix<sub class=opt>opt</sub></dd>
  <dd>unsigned-suffix long-long-suffix<sub class=opt>opt</sub></dd>
  <dd>unsigned-suffix size-suffix<sub class=opt>opt</sub></dd>
  <dd><ins>unsigned-suffix bit-precise-int-suffix<sub class=opt>opt</sub></ins></dd>
  <dd>long-suffix unsigned-suffix<sub class=opt>opt</sub></dd>
  <dd>long-long-suffix unsigned-suffix<sub class=opt>opt</sub></dd>
  <dd>size-suffix unsigned-suffix<sub class=opt>opt</sub></dd>
  <dd><ins>bit-precise-int-suffix unsigned-suffix<sub class=opt>opt</sub></ins></dd>
</dl>
<dl class=grammar>
  <dt><g-term>unsigned-suffix</g-term>: one of</dt>
  <dd><code><h- data-h=id>u</h-></code> <code><h- data-h=id>U</h-></code></dd>
</dl>
<dl class=grammar>
  <dt><g-term>long-suffix</g-term>: one of</dt>
  <dd><code><h- data-h=id>l</h-></code> <code><h- data-h=id>L</h-></code></dd>
</dl>
<dl class=grammar>
  <dt><g-term>long-long-suffix</g-term>: one of</dt>
  <dd><code><h- data-h=id>ll</h-></code> <code><h- data-h=id>LL</h-></code></dd>
</dl>
<dl class=grammar>
  <dt><g-term>size-suffix</g-term>: one of</dt>
  <dd><code><h- data-h=id>z</h-></code> <code><h- data-h=id>Z</h-></code></dd>
</dl>
<dl class=grammar>
  <dt><ins><g-term>bit-precise-int-suffix</g-term>: one of</ins></dt>
  <dd><ins><code><h- data-h=id>wb</h-></code> <code><h- data-h=id>WB</h-></code></ins></dd>
</dl>
</diff-block>

<p>Change table <a href=https://eel.is/c++draft/tab:lex.icon.type>[tab:lex.icon.type]</a> as follows:
</p>
<diff-block>
<table class=wording>

  <tr>
    <th><g-term><span class=word>integer-suffix</span></g-term></th>
    <th><g-term>decimal-literal</g-term></th>
    <th><g-term>integer-literal</g-term> other than <g-term>decimal-literal</g-term></th>
  </tr>

  <tr>
    <td>none</td>
    <td>
      <code-block class=borderless><ins>“</ins><h- data-h=kw_type>int</h-><ins>”</ins>
<ins>“</ins><h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins>
<ins>“</ins><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins></code-block>
    </td>
    <td>
      <code-block class=borderless><ins>“</ins><h- data-h=kw_type>int</h-><ins>”</ins>
<ins>“</ins><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>int</h-><ins>”</ins>
<ins>“</ins><h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins>
<ins>“</ins><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins>
<ins>“</ins><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins>
<ins>“</ins><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins></code-block>
    </td>
  </tr>

  <tr>
    <td><code><h- data-h=id>u</h-></code> or <code><h- data-h=id>U</h-></code></td>
    <td>
      <code-block class=borderless><ins>“</ins><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>int</h-><ins>”</ins>
<ins>“</ins><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins>
<ins>“</ins><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins></code-block>
    </td>
    <td>
      <code-block class=borderless><ins>“</ins><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>int</h-><ins>”</ins>
<ins>“</ins><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins>
<ins>“</ins><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins></code-block>
    </td>
  </tr>

  <tr>
    <td><code><h- data-h=id>l</h-></code> or <code><h- data-h=id>L</h-></code></td>
    <td>
      <code-block class=borderless><ins>“</ins><h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins>
<ins>“</ins><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins></code-block>
    </td>
    <td>
      <code-block class=borderless><ins>“</ins><h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins>
<ins>“</ins><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins>
<ins>“</ins><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins>
<ins>“</ins><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins></code-block>
    </td>
  </tr>

  <tr>
    <td>Both <code><h- data-h=id>u</h-></code> or <code><h- data-h=id>U</h-></code> and <code><h- data-h=id>l</h-></code> or <code><h- data-h=id>L</h-></code></td>
    <td>
      <code-block class=borderless><ins>“</ins><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins>
<ins>“</ins><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins></code-block>
    </td>
    <td>
      <code-block class=borderless><ins>“</ins><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins>
<ins>“</ins><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins></code-block>
    </td>
  </tr>

  <tr>
    <td>Both <code><h- data-h=id>u</h-></code> or <code><h- data-h=id>U</h-></code> and <code><h- data-h=id>ll</h-></code> or <code><h- data-h=id>LL</h-></code></td>
    <td>
      <code-block class=borderless><ins>“</ins><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins></code-block>
    </td>
    <td>
      <code-block class=borderless><ins>“</ins><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-><ins>”</ins></code-block>
    </td>
  </tr>

  <tr>
    <td><code><h- data-h=id>z</h-></code> or <code><h- data-h=id>Z</h-></code></td>
    <td>
      the signed integer type corresponding to
      <ins>the type named by</ins>
      <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>size_t</h-></code> (<a href=https://eel.is/c++draft/support.types.layout>[support.types.layout]</a>)
    </td>
    <td>
      the signed integer type corresponding to
      <ins>the type named by</ins>
      <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>size_t</h-></code><br/><br/>
      <ins>the type named by</ins>
      <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>size_t</h-></code>
    </td>
  </tr>

  <tr>
    <td>Both <code><h- data-h=id>u</h-></code> or <code><h- data-h=id>U</h-></code> and <code><h- data-h=id>z</h-></code> or <code><h- data-h=id>Z</h-></code></td>
    <td>
      <ins>the type named by</ins>
      <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>size_t</h-></code>
    </td>
    <td>
      <ins>the type named by</ins>
      <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>size_t</h-></code>
    </td>
  </tr>
  <tr>
    <td><ins><code><h- data-h=id>wb</h-></code> or <code><h- data-h=id>WB</h-></code></ins></td>
    <td>
      <ins>“<code><h- data-h=kw_type>_BitInt</h-></code> of width <math display=inline><mi>N</mi></math>”,
      where <math display=inline><mi>N</mi></math> is the lowest integer <math display=inline><mrow><mo>≥</mo><mn>1</mn></mrow></math>
      so that the value of the literal can be represented by the type</ins>
    </td>
    <td>
      <ins>“<code><h- data-h=kw_type>_BitInt</h-></code> of width <math display=inline><mi>N</mi></math>”,
      where <math display=inline><mi>N</mi></math> is the lowest integer <math display=inline><mrow><mo>≥</mo><mn>1</mn></mrow></math>
      so that the value of the literal can be represented by the type</ins>
    </td>
  </tr>
  <tr>
    <td>
      <ins>Both <code><h- data-h=id>u</h-></code> or <code><h- data-h=id>U</h-></code> and<br/><code><h- data-h=id>wb</h-></code> or <code><h- data-h=id>WB</h-></code></ins>
    </td>
    <td>
      <ins>“<code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-></code> of width <math display=inline><mi>N</mi></math>”,
      where <math display=inline><mi>N</mi></math> is the lowest integer <math display=inline><mrow><mo>≥</mo><mn>1</mn></mrow></math>
      so that the value of the literal can be represented by the type</ins>
    </td>
    <td>
      <ins>“<code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-></code> of width <math display=inline><mi>N</mi></math>”,
      where <math display=inline><mi>N</mi></math> is the lowest integer <math display=inline><mrow><mo>≥</mo><mn>1</mn></mrow></math>
      so that the value of the literal can be represented by the type</ins>
    </td>
  </tr>
</table>
</diff-block>

<note-block><p><intro-></intro-> 
The existing rows are adjusted for consistency.
We usually aim to use the <q>quoted</q> spellings of types
like “<code><h- data-h=kw_type>_BitInt</h-></code> of width <math display=inline><mi>N</mi></math>”
in core wording
instead of the <g-term>type-id</g-term> spellings.
Adding a quoted spelling for bit-precise integers would reveal
that the previous rows "incorrectly" use <g-term>type-id</g-term>s.
</p></note-block>

<p>Change <a href=https://eel.is/c++draft/lex.icon#4>[lex.icon] paragraph 4</a> as follows:
</p>
<diff-block>
<p>Except for <g-term>integer-literal</g-term>s containing a <g-term>size-suffix</g-term>
<ins>or <g-term>bit-precise-int-suffix</g-term></ins>,
if the value of an <g-term>integer-literal</g-term> cannot be represented
by any type in its list and an extended integer type (<a href=https://eel.is/c++draft/basic.fundamental>[basic.fundamental]</a>)
can represent its value,
it may have that extended integer type.
[…]</p>

<p>[<i>Note</i>: 
An <g-term>integer-literal</g-term> with a <code><h- data-h=id>z</h-></code> or <code><h- data-h=id>Z</h-></code> suffix
is ill-formed if it cannot be represented by <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>size_t</h-></code>.
<ins>An <g-term>integer-literal</g-term> with a <code><h- data-h=id>wb</h-></code> or <code><h- data-h=id>WB</h-></code> suffix
is ill-formed if it cannot be represented by any bit-precise integer type
because the necessary width is greater than
<code><h- data-h=id>BITINT_MAXWIDTH</h-></code> (<a href=https://eel.is/c++draft/climits.syn>[climits.syn]</a>).</ins>
 — <i>end note</i>]
</p></diff-block>

<h4 id=basic.fundamental><a class=para href=#basic%2efundamental></a>[basic.fundamental]</h4>

<p>Change <a href=https://eel.is/c++draft/basic.fundamental#1>[basic.fundamental] paragraph 1</a> as follows:
</p>
<diff-block>
<p>There are five <dfn>standard signed integer types</dfn>:
<q><code><h- data-h=kw_type>signed</h-> <h- data-h=kw_type>char</h-></code></q>,
<q><code><h- data-h=kw_type>short</h-> <h- data-h=kw_type>int</h-></code></q>,
<q><code><h- data-h=kw_type>int</h-></code></q>,
<q><code><h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></q>, and
<q><code><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></q>.
In this list,
each type provides at least as much storage as those
preceding it in the list.
<ins>There is also a distinct <dfn>bit-precise signed integer type</dfn>
“<code><h- data-h=kw_type>_BitInt</h-></code> of width <math display=inline><mi>N</mi></math>”
for each <math display=inline><mrow><mn>1</mn><mo>≤</mo><mi>N</mi><mo>≤</mo><mtext><tt->BITINT_MAXWIDTH</tt-></mtext></mrow></math> (<a href=https://eel.is/c++draft/climits.syn>[climits.syn]</a>).</ins>
There may also be implementation-defined
<dfn>extended signed integer types</dfn>.
The standard<ins>, bit-precise,</ins> and extended signed integer types are collectively called
<dfn>signed integer types</dfn>.
The range of representable values for a signed integer type is
<math display=inline>
  <msup>
    <mn>-2</mn>
    <mrow><mi>N</mi><mo>−</mo><mn>1</mn></mrow>
  </msup>
</math>
to
<math display=inline>
  <mrow>
    <msup>
      <mn>2</mn>
      <mrow><mi>N</mi><mo>−</mo><mn>1</mn></mrow>
    </msup>
    <mo>−</mo>
    <mn>1</mn>
  </mrow>
</math>
(inclusive),
where <math display=inline><mi>N</mi></math> is called the <dfn>width</dfn> of the type.
</p>
<p>[<i>Note</i>: 
Plain <code><h- data-h=kw_type>int</h-></code>s are intended to have
the natural width suggested by the architecture of the execution environment;
the other signed integer types are provided to meet special needs.
 — <i>end note</i>]
</p></diff-block>

<warning-block><p><intro-></intro-> 
This change deviates from C at the time of writing;
C2y does not yet allow <code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>1</h-><h- data-h=sym_par>)</h-></code>,
but may allow it following <a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg14/www/docs/n3644%2epdf">[N3644]</a>.
</p></warning-block>

<p>Change <a href=https://eel.is/c++draft/basic.fundamental#2>[basic.fundamental] paragraph 2</a> as follows:
</p>
<diff-block>
<p>For each of the standard signed integer types,
there exists a corresponding (but different)
<dfn>standard unsigned integer type</dfn>:
<q><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>char</h-></code></q>,
<q><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>short</h-></code></q>,
<q><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>int</h-></code></q>,
<q><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></q>, and
<q><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></q>.
<ins>For each bit-precise signed integer type
“<code><h- data-h=kw_type>_BitInt</h-></code> of width <math display=inline><mi>N</mi></math>”,
there exists a corresponding <dfn>bit-precise unsigned integer type</dfn>
“<code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-></code> of width <math display=inline><mi>N</mi></math>”.</ins>
<del>Likewise, for</del> <ins>For</ins> each of the extended signed integer types,
there exists a corresponding <dfn>extended unsigned integer type</dfn>.
The standard<ins>, bit-precise,</ins> and extended unsigned integer types
are collectively called <dfn>unsigned integer types</dfn>.
An unsigned integer type has the same width <math display=inline><mi>N</mi></math>
as the corresponding signed integer type.
The range of representable values for the unsigned type is
<math display=inline><mn>0</mn></math> to
<math display=inline>
  <msup>
    <mn>2</mn>
    <mrow><mi>N</mi><mo>−</mo><mn>1</mn></mrow>
  </msup>
</math> (inclusive);
arithmetic for the unsigned type is performed modulo <math display=inline><msup><mn>2</mn><mi>N</mi></msup></math>.
</p>
<p>[<i>Note</i>: 
Unsigned arithmetic does not overflow.
Overflow for signed arithmetic yields undefined behavior (<a href=https://eel.is/c++draft/expr.pre>[expr.pre]</a>).
 — <i>end note</i>]
</p></diff-block>



<p>Change <a href=https://eel.is/c++draft/basic.fundamental#5>[basic.fundamental] paragraph 5</a> as follows:
</p>
<diff-block>
<p>[…]
The standard signed integer types and standard unsigned integer types
are collectively called the <dfn>standard integer types</dfn><del>, and the</del>
<ins>. The bit-precise signed integer types and bit-precise unsigned integer types
are collectively called the <dfn>bit-precise integer types</dfn>. The</ins>
extended signed integer types and extended
unsigned integer types are collectively called the
<dfn>extended integer types</dfn>.
</p></diff-block>

<h4 id=conv.rank><a class=para href=#conv%2erank></a>[conv.rank]</h4>

<p>Change <a href=https://eel.is/c++draft/conv.rank#1>[conv.rank] paragraph 1</a> as follows:
</p>
<diff-block>

<p>Every integer type has an <i>integer conversion rank</i> defined as follows:
</p>
<ul>
  <li>
    No two signed integer types other than <code><h- data-h=kw_type>char</h-></code> and <code><h- data-h=kw_type>signed</h-> <h- data-h=kw_type>char</h-></code>
    (if <h- data-h=kw>char</h-> is signed) have the same rank, even if they have the same representation.
  </li>
  <li>
    The rank of a signed integer type is greater than the rank
    of any signed integer type with a smaller width.
  </li>
  <li>
    The rank of <code><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code> is greater than the rank of <code><h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code>,
    which is greater than the rank of <code><h- data-h=kw_type>int</h-></code>,
    which is greater than the rank of <code><h- data-h=kw_type>short</h-> <h- data-h=kw_type>int</h-></code>,
    which is greater than the rank of <code><h- data-h=kw_type>signed</h-> <h- data-h=kw_type>char</h-></code>.
  </li>
  <li>
    The rank of any unsigned integer type equals the rank of the
    corresponding signed integer type.
  </li>
  <li>
    The rank of any standard integer type is greater than the rank
    of <ins>any bit-precise integer type with the same width
    and of</ins> any extended integer type with the same width.
  </li>
  <li>
    The rank of <code><h- data-h=kw_type>char</h-></code> equals the rank of <code><h- data-h=kw_type>signed</h-> <h- data-h=kw_type>char</h-></code>
    and <code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>char</h-></code>.
  </li>
  <li>
    The rank of <code><h- data-h=kw_type>bool</h-></code> is less than the rank of all
    standard integer types.
  </li>
  <li>
    The ranks of <code><h- data-h=kw_type>char8_t</h-></code>, <code><h- data-h=kw_type>char16_t</h-></code>, <code><h- data-h=kw_type>char32_t</h-></code>, and
    <code><h- data-h=kw_type>wchar_t</h-></code> equal the ranks of their underlying
    types (<a href=https://eel.is/c++draft/basic.fundamental>[basic.fundamental]</a>).
  </li>
  <li>
    The rank of any extended signed integer type relative to another
    extended signed integer type with the same width
    <ins>and relative to a bit-precise signed integer type with the same width</ins>
    is implementation-defined,
    but still subject to the other rules for determining the integer conversion rank.
  </li>
  <li>
    For all integer types <code><h- data-h=id>T1</h-></code>, <code><h- data-h=id>T2</h-></code>, and <code><h- data-h=id>T3</h-></code>, if
    <code><h- data-h=id>T1</h-></code> has greater rank than <code><h- data-h=id>T2</h-></code> and <code><h- data-h=id>T2</h-></code> has greater
    rank than <code><h- data-h=id>T3</h-></code>, then <code><h- data-h=id>T1</h-></code> has greater rank than
    <code><h- data-h=id>T3</h-></code>.
  </li>
</ul>

<p>[<i>Note</i>: 
The integer conversion rank is used in the definition of the integral
promotions (<a href=https://eel.is/c++draft/conv.prom>[conv.prom]</a>) and the usual arithmetic
conversions (<a href=https://eel.is/c++draft/expr.arith.conv>[expr.arith.conv]</a>).
 — <i>end note</i>]
</p></diff-block>

<h4 id=conv.prom><a class=para href=#conv%2eprom></a>[conv.prom]</h4>

<note-block><p><intro-></intro-> 
These changes mirror the C semantics described in
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg14/www/docs/n3550%2epdf">[N3550]</a> §6.3.2.1 Boolean, characters, and integers.
</p></note-block>

<p>Change <a href=https://eel.is/c++draft/conv.prom#2>[conv.prom] paragraph 2</a> as follows:
</p>
<diff-block>
<p>A prvalue that
</p><ul>
  <li>is not a converted bit-field <del>and</del> <ins>,</ins></li>
  <li>
    has an integer type other than
    <ins>a bit-precise integer type,</ins>
    <code><h- data-h=kw_type>bool</h-></code>, <code><h- data-h=kw_type>char8_t</h-></code>, <code><h- data-h=kw_type>char16_t</h-></code>, <code><h- data-h=kw_type>char32_t</h-></code>,
    or <code><h- data-h=kw_type>wchar_t</h-></code><ins>, and</ins>
  </li>
  <li>
    whose integer conversion rank (<a href=https://eel.is/c++draft/conv.rank>[conv.rank]</a>)
    is less than the rank of <code><h- data-h=kw_type>int</h-></code>
  </li>
</ul>
<p>can be converted to
a prvalue of type <code><h- data-h=kw_type>int</h-></code>
if <code><h- data-h=kw_type>int</h-></code> can represent all the values of the source type;
otherwise, the source prvalue can be converted to
a prvalue of type <code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>int</h-></code>.
</p></diff-block>

<p>Change <a href=https://eel.is/c++draft/conv.prom#5>[conv.prom] paragraph 5</a> as follows:
</p>
<diff-block>
<p>A converted bit-field of integral type
<ins>other than a bit-precise integer type</ins>
can be converted to a prvalue of type <code><h- data-h=kw_type>int</h-></code>
if <code><h- data-h=kw_type>int</h-></code> can represent all the values of the bit-field;
otherwise, it can be converted to <code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>int</h-></code>
if <code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>int</h-></code> can represent all the values of the bit-field.
</p></diff-block>

<h4 id=dcl.type.general><a class=para href=#dcl%2etype%2egeneral></a>[dcl.type.general]</h4>

<p>Change <a href=https://eel.is/c++draft/dcl.type.general#2>[dcl.type.general] paragraph 2</a> as follows:
</p>
<diff-block>
<p>As a general rule,
at most one <g-term>defining-type-specifier</g-term> is allowed
in the complete <g-term>decl-specifier-seq</g-term> of a declaration
or in a <g-term>defining-type-specifier-seq</g-term>,
and at most one <g-term>type-specifier</g-term> is allowed in a <g-term>type-specifier-seq</g-term>.
The only exceptions to this rule are the following:
</p><ul>
  <li><code><h- data-h=kw>const</h-></code> can be combined with any type specifier except itself.</li>
  <li><code><h- data-h=kw>volatile</h-></code> can be combined with any type specifier except itself.</li>
  <li>
    <code><h- data-h=kw_type>signed</h-></code> or <code><h- data-h=kw_type>unsigned</h-></code> can be combined with
    <code><h- data-h=kw_type>char</h-></code>, <code><h- data-h=kw_type>long</h-></code>, <code><h- data-h=kw_type>short</h-></code>, <del>or</del> <code><h- data-h=kw_type>int</h-></code><ins>, or
    a <g-term>bit-precise-int-type-specifier</g-term>.</ins>
  </li>
  <li><code><h- data-h=kw_type>short</h-></code> or <code><h- data-h=kw_type>long</h-></code> can be combined with <code><h- data-h=kw_type>int</h-></code>.</li>
  <li><code><h- data-h=kw_type>long</h-></code> can be combined with <code><h- data-h=kw_type>double</h-></code>.</li>
  <li><code><h- data-h=kw_type>long</h-></code> can be combined with <code><h- data-h=kw_type>long</h-></code>.</li>
</ul>
</diff-block>

<h4 id=dcl.type.simple><a class=para href=#dcl%2etype%2esimple></a>[dcl.type.simple]</h4>

<p>Change <a href=https://eel.is/c++draft/dcl.type.simple#1>[dcl.type.simple] paragraph 1</a> as follows:
</p>
<diff-block>
<p>The simple type specifiers are
</p>
<dl class=grammar>
  <dt><g-term>simple-type-specifier</g-term>:</dt>
  <dd>nested-name-specifier<sub class=opt>opt</sub> type-name</dd>
  <dd>nested-name-specifier <code><h- data-h=kw>template</h-></code> simple-template-id</dd>
  <dd>computed-type-specifier</dd>
  <dd>placeholder-type-specifier</dd>
  <dd><ins>bit-precise-int-type-specifier</ins></dd>
  <dd>nested-name-specifier<sub class=opt>opt</sub> template-name</dd>
  <dd><code><h- data-h=kw_type>char</h-></code></dd>
  <dd><code><h- data-h=kw_type>char8_t</h-></code></dd>
  <dd><code><h- data-h=kw_type>char16_t</h-></code></dd>
  <dd><code><h- data-h=kw_type>char32_t</h-></code></dd>
  <dd><code><h- data-h=kw_type>wchar_t</h-></code></dd>
  <dd><code><h- data-h=kw_type>bool</h-></code></dd>
  <dd><code><h- data-h=kw_type>short</h-></code></dd>
  <dd><code><h- data-h=kw_type>int</h-></code></dd>
  <dd><code><h- data-h=kw_type>long</h-></code></dd>
  <dd><code><h- data-h=kw_type>signed</h-></code></dd>
  <dd><code><h- data-h=kw_type>unsigned</h-></code></dd>
  <dd><code><h- data-h=kw_type>float</h-></code></dd>
  <dd><code><h- data-h=kw_type>double</h-></code></dd>
  <dd><code><h- data-h=kw_type>void</h-></code></dd>

  <dt><g-term>type-name</g-term>:</dt>
  <dd>class-name</dd>
  <dd>enum-name</dd>
  <dd>typedef-name</dd>

  <dt><g-term>computed-type-specifier</g-term>:</dt>
  <dd>decltype-specifier</dd>
  <dd>pack-index-specifier</dd>
  <dd>splice-type-specifier</dd>

  <dt><ins><g-term>bit-precise-int-type-specifier</g-term>:</ins></dt>
  <dd><ins><code><h- data-h=kw_type>_BitInt</h-></code> <code><h- data-h=sym_par>(</h-></code> constant-expression <code><h- data-h=sym_par>)</h-></code></ins></dd>
</dl>
</diff-block>

<p>Change table <a href=https://eel.is/c++draft/tab:dcl.type.simple>[tab:dcl.type.simple]</a> as follows:
</p>


<diff-block>
  <table>
    <tr>
      <th>Specifier(s)</th>
      <th>Type</th>
    </tr>
    <tr>
      <td><g-term>type-name</g-term></td>
      <td>the type named</td>
    </tr>
    <tr>
      <td><g-term>simple-template-id</g-term></td>
      <td>the type as defined in <a href=https://eel.is/c++draft/temp.names>[temp.names]</a></td>
    </tr>
    <tr>
      <td><g-term>decltype-specifier</g-term></td>
      <td>the type as defined in <a href=https://eel.is/c++draft/dcl.type.decltype>[dcl.type.decltype]</a></td>
    </tr>
    <tr>
      <td><g-term>pack-index-specifier</g-term></td>
      <td>the type as defined in <a href=https://eel.is/c++draft/dcl.type.pack.index>[dcl.type.pack.index]</a></td>
    </tr>
    <tr>
      <td><g-term>placeholder-type-specifier</g-term></td>
      <td>the type as defined in <a href=https://eel.is/c++draft/dcl.spec.auto>[dcl.spec.auto]</a></td>
    </tr>
    <tr>
      <td><g-term>template-name</g-term></td>
      <td>the type as defined in <a href=https://eel.is/c++draft/dcl.type.class.deduct>[dcl.type.class.deduct]</a></td>
    </tr>
    <tr>
      <td><g-term>splice-type-specifier</g-term></td>
      <td>the type as defined in <a href=https://eel.is/c++draft/dcl.type.splice>[dcl.type.splice]</a></td>
    </tr>
    <tr>
      <td><ins><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><math display=inline><mi>N</mi></math><h- data-h=sym_par>)</h-></code></ins></td>
      <td><ins>“<code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-></code> of width <math display=inline><mi>N</mi></math>”</ins></td>
    </tr>
    <tr>
      <td><ins><code><h- data-h=kw_type>signed</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><math display=inline><mi>N</mi></math><h- data-h=sym_par>)</h-></code></ins></td>
      <td><ins>“<code><h- data-h=kw_type>_BitInt</h-></code> of width <math display=inline><mi>N</mi></math>”</ins></td>
    </tr>
    <tr>
      <td><ins><code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><math display=inline><mi>N</mi></math><h- data-h=sym_par>)</h-></code></ins></td>
      <td><ins>“<code><h- data-h=kw_type>_BitInt</h-></code> of width <math display=inline><mi>N</mi></math>”</ins></td>
    </tr>
    <tr><td><code><h- data-h=kw_type>char</h-></code></td><td><q><code><h- data-h=kw_type>char</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>char</h-></code></td><td><q><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>char</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>signed</h-> <h- data-h=kw_type>char</h-></code></td><td><q><code><h- data-h=kw_type>signed</h-> <h- data-h=kw_type>char</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>char8_t</h-></code></td><td><q><code><h- data-h=kw_type>char8_t</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>char16_t</h-></code></td><td><q><code><h- data-h=kw_type>char16_t</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>char32_t</h-></code></td><td><q><code><h- data-h=kw_type>char32_t</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>bool</h-></code></td><td><q><code><h- data-h=kw_type>bool</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>unsigned</h-></code></td><td><q><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>int</h-></code></td><td><q><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>signed</h-></code></td><td><q><code><h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>signed</h-> <h- data-h=kw_type>int</h-></code></td><td><q><code><h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>int</h-></code></td><td><q><code><h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>short</h-> <h- data-h=kw_type>int</h-></code></td><td><q><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>short</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>short</h-></code></td><td><q><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>short</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></td><td><q><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-></code></td><td><q><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></td><td><q><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-></code></td><td><q><code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>signed</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></td><td><q><code><h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>signed</h-> <h- data-h=kw_type>long</h-></code></td><td><q><code><h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>signed</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></td><td><q><code><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>signed</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-></code></td><td><q><code><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></td><td><q><code><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-></code></td><td><q><code><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></td><td><q><code><h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>long</h-></code></td><td><q><code><h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>signed</h-> <h- data-h=kw_type>short</h-> <h- data-h=kw_type>int</h-></code></td><td><q><code><h- data-h=kw_type>short</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>signed</h-> <h- data-h=kw_type>short</h-></code></td><td><q><code><h- data-h=kw_type>short</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>short</h-> <h- data-h=kw_type>int</h-></code></td><td><q><code><h- data-h=kw_type>short</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>short</h-></code></td><td><q><code><h- data-h=kw_type>short</h-> <h- data-h=kw_type>int</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>wchar_t</h-></code></td><td><q><code><h- data-h=kw_type>wchar_t</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>float</h-></code></td><td><q><code><h- data-h=kw_type>float</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>double</h-></code></td><td><q><code><h- data-h=kw_type>double</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>long</h-> <h- data-h=kw_type>double</h-></code></td><td><q><code><h- data-h=kw_type>long</h-> <h- data-h=kw_type>double</h-></code></q></td></tr>
    <tr><td><code><h- data-h=kw_type>void</h-></code></td><td><q><code><h- data-h=kw_type>void</h-></code></q></td></tr>
  </table>
</diff-block>

<p>Immediately following <a href=https://eel.is/c++draft/dcl.type.simple#3>[dcl.type.simple] paragraph 3</a>,
add a new paragraph as follows:
</p>
<ins-block>
<p>Within a <g-term>bit-precise-int-type-specifier</g-term>,
the <g-term>constant-expression</g-term> shall be a converted constant expression of type
<code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>size_t</h-></code> (<a href=https://eel.is/c++draft/expr.const>[expr.const]</a>).
Its value <math display=inline><mi>N</mi></math> specifies the width
of the bit-precise integer type (<a href=https://eel.is/c++draft/basic.fundamental>[basic.fundamental]</a>).
The program is ill-formed unless
<math display=inline>
  <mrow>
    <mn>1</mn>
    <mo>≤</mo>
    <mi>N</mi>
    <mo>≤</mo>
    <mtext><tt->BITINT_MAXWIDTH</tt-></mtext>
  </mrow>
</math> (<a href=https://eel.is/c++draft/climits.syn>[climits.syn]</a>).
</p></ins-block>

<h4 id=dcl.enum><a class=para href=#dcl%2eenum></a>[dcl.enum]</h4>

<note-block><p><intro-></intro-> 
The intent is to ban <code><h- data-h=kw_type>_BitInt</h-></code> from being the underlying type of enumerations,
matching the current restrictions in C.
See <a href=#underlying-bitint>§4.3. Underlying type of enumerations</a>.
</p></note-block>

<p>Change <a href=https://eel.is/c++draft/dcl.enum#2>[dcl.enum] paragraph 2</a> as follows:
</p>
<diff-block>
<p>[…]
The <g-term>type-specifier-seq</g-term> of an <g-term>enum-base</g-term>
shall name an integral type
<ins>other than a bit-precise integer type</ins>;
any cv-qualification is ignored.
[…]
</p></diff-block>

<p>Change <a href=https://eel.is/c++draft/dcl.enum#5>[dcl.enum] paragraph 5</a> as follows:
</p>
<diff-block>
<p>[…]
If the underlying type is not fixed,
the type of each enumerator prior ot the closing brace is determined as follows:
</p>
<ul>
  <li>
    If an initializer is specified for an enumerator,
    the <g-term>constant-expression</g-term> shall be
    an integral constant expression (<a href=https://eel.is/c++draft/expr.const>[expr.const]</a>)
    <ins>whose type is not a bit-precise integer type</ins>.
    If the expression has unscoped enumeration type,
    the enumerator has the underlying type of that enumeration type,
    otherwise it has the same type as the expression.
  </li>
  <li>
    If no initializer is specified for the first enumerator,
    its type is an unspecified signed <del>integral</del> <ins>integer</ins> type
    <ins>other than a bit-precise integer type</ins>.
  </li>
  <li>
    Otherwise<ins>,</ins> the type of the enumerator is the same as
    that of the preceding enumerator<ins>,</ins>
    unless the incremented value is not representable in that type,
    in which case the type is an unspecified integral type
    <ins>other than a bit-precise integer type</ins>
    sufficient to contain the incremented value.
    If no such type exists, the program is ill-formed.
  </li>
</ul>
</diff-block>

<p>Change <a href=https://eel.is/c++draft/dcl.enum#7>[dcl.enum] paragraph 7</a> as follows:
</p>
<diff-block>
<p>For an enumeration whose underlying type is not fixed,
the underlying type is an integral type
that can represent all the enumerator values defined in the enumeration.
If no integral type can represent all the enumerator values,
the enumeration is ill-formed.
It is implementation-defined which integral type is used as the underlying type<ins>,</ins>
except that
</p><ul>
  <li>
    <ins>the underlying type shall not be a bit-precise integer type and</ins>
  </li>
  <li>
    the underlying type shall not be larger than <code><h- data-h=kw_type>int</h-></code>
    unless the value of an enumerator
    cannot fit in an <code><h- data-h=kw_type>int</h-></code> or <code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>int</h-></code>.
  </li>
</ul>
<p>If the <g-term>enumerator-list</g-term> is empty,
the underlying type is as if the enumeration had a single enumerator with value 0.
</p></diff-block>

<h4 id=temp.deduct.general><a class=para href=#temp%2ededuct%2egeneral></a>[temp.deduct.general]</h4>

<p>Add a bullet to <a href=https://eel.is/c++draft/temp.deduct.general#note-8>[temp.deduct.general] note 8</a> as follows:
</p>
<diff-block>
<p>[<i>Note</i>: 
Type deduction can fail for the following reasons:
</p>
<ul>
  <li>Attempting to instantiate a pack expansion containing multiple packs of differing lengths.</li>
  <li>
    Attempting to create an array with an element type that is <code><h- data-h=kw_type>void</h-></code>,
    a function type, or a reference type,
    or attempting to create an array with a size that is zero or negative.
    <br/>[<i>Example</i>: 
    <code-block class=borderless><h- data-h=kw>template</h-> <h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>f</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-><h- data-h=sym_sqr>[</h-><h- data-h=num>5</h-><h- data-h=sym_sqr>]</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw_type>int</h-> <h- data-h=id>I</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>f</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>int</h-><h- data-h=sym_op>&gt;</h-><h- data-h=sym_par>(</h-><h- data-h=num>0</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw_type>int</h-> <h- data-h=id>j</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>f</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>void</h-><h- data-h=sym_op>&gt;</h-><h- data-h=sym_par>(</h-><h- data-h=num>0</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>invalid array</h-></f-serif></code-block>
     — <i>end example</i>]
  </li>
  <li>
    <ins>Attempting to create a bit-precise integer type of invalid width (<a href=https://eel.is/c++draft/basic.fundamental>[basic.fundamental]</a>).
    <br/>[<i>Example</i>: 
    <code-block class=borderless><ins><h- data-h=kw>template</h-> <h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>int</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</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>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>f</h-><h- data-h=sym_op>&lt;</h-><h- data-h=num>0</h-><h- data-h=sym_op>&gt;</h-><h- data-h=sym_par>(</h-><h- data-h=num>0</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>invalid bit-precise integer</h-></f-serif></ins></code-block>
     — <i>end example</i>]
    </ins>
  </li>
  <li>[…]</li>
</ul>
<p> — <i>end note</i>]
</p></diff-block>

<h4 id=temp.deduct.type><a class=para href=#temp%2ededuct%2etype></a>[temp.deduct.type]</h4>

<p>Change <a href=https://eel.is/c++draft/temp.deduct.type#2>[temp.deduct.type] paragraph 2</a> as follows:
</p>
<diff-block>
<p>[…]
The type of a type parameter is only deduced from an array bound
<ins>or bit-precise integer width</ins>
if it is not otherwise deduced.
</p></diff-block>

<p>Change <a href=https://eel.is/c++draft/temp.deduct.type#3>[temp.deduct.type] paragraph 3</a> as follows:
</p>
<diff-block>
<p>A given type <code><h- data-h=id>P</h-></code> can be composed from a number of other types,
templates, and constant template argument values:
</p><ul>
  <li>
    A function type includes the types of each of the function parameters,
    the return type, and its exception specification.
  </li>
  <li>
    A pointer-to-member type includes the type of the class object pointed to
    and the type of the member pointed to.
  </li>
  <li>
    A type that is a specialization of a class template (e.g., <code><h- data-h=id>A</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>int</h-><h- data-h=sym_op>&gt;</h-></code>) includes the types,
    templates, and constant template argument values
    referenced by the template argument list of the specialization.
  </li>
  <li>
    An array type includes the array element type and the value of the array bound.
  </li>
  <li>
    <ins>A bit-precise integer type includes the integer width.</ins>
  </li>
</ul>
</diff-block>

<p>Change <a href=https://eel.is/c++draft/temp.deduct.type#5>[temp.deduct.type] paragraph 5</a> as follows:
</p>
<diff-block>
<p>The non-deduced contexts are:
</p><ul>
  <li>[…]</li>
  <li>
    A constant template argument <del>or</del> <ins>,</ins> an array bound<ins>, or
    a bit-precise integer width,</ins>
    in <ins>any of</ins> which a subexpression references a template parameter.
    <br/><ins>[<i>Example</i>: 
    <code-block class=borderless><ins><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id_type>size_t</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</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>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id_type>size_t</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=kw_type>void</h-> <h- data-h=id>g</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-> <h- data-h=sym_op>+</h-> <h- data-h=num>1</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>f</h-><h- data-h=sym_par>(</h-><h- data-h=num>100</h-><h- data-h=num_deco>wb</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</h-></f-serif><h- data-h=cmt>, </h-><code><h- data-h=id>N</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>8</h-></code>
<h- data-h=id>g</h-><h- data-h=sym_par>(</h-><h- data-h=num>100</h-><h- data-h=num_deco>wb</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>error: no argument for deduced </h-><code><h- data-h=id>N</h-></code></f-serif></ins></code-block>
     — <i>end example</i>]</ins>
  </li>
  <li>[…]</li>
</ul>
</diff-block>

<p>Change <a href=https://eel.is/c++draft/temp.deduct.type#8>[temp.deduct.type] paragraph 8</a> as follows:
</p>
<diff-block>
<p>A type template argument <code><h- data-h=id>T</h-></code>,
a constant template argument <code><h- data-h=id>i</h-></code>,
a template template argument <code><h- data-h=id>TT</h-></code> denoting a class template or an alias template,
or a template template argument <code><h- data-h=id>VV</h-></code> denoting a variable template or a concept
can be deduced if <code><h- data-h=id>P</h-></code> and <code><h- data-h=id>A</h-></code> have one of the following forms:
</p>
<code-block class=borderless><i><h- data-h=id>cv</h-></i><sub class=opt><h- data-h=id>opt</h-></sub> <h- data-h=id>T</h->
<h- data-h=id>T</h-><h- data-h=sym_op>*</h->
<h- data-h=id>T</h-><h- data-h=sym_op>&amp;</h->
<h- data-h=id>T</h-><h- data-h=sym_op>&amp;&amp;</h->
<h- data-h=id>T</h-><sub class=opt><h- data-h=id>opt</h-></sub><h- data-h=sym_sqr>[</h-><h- data-h=id>i</h-><sub class=opt><h- data-h=id>opt</h-></sub><h- data-h=sym_sqr>]</h->
<ins><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>i</h-><sub class=opt><h- data-h=id>opt</h-></sub><h- data-h=sym_par>)</h-></ins>
<h- data-h=id>T</h-><sub class=opt><h- data-h=id>opt</h-></sub><h- data-h=sym_par>(</h-><h- data-h=id>T</h-><sub class=opt><h- data-h=id>opt</h-></sub><h- data-h=sym_par>)</h-> <h- data-h=kw>noexcept</h-><h- data-h=sym_par>(</h-><h- data-h=id>i</h-><sub class=opt><h- data-h=id>opt</h-></sub><h- data-h=sym_par>)</h->
<h- data-h=id>T</h-><sub class=opt><h- data-h=id>opt</h-></sub> <h- data-h=id>T</h-><sub class=opt><h- data-h=id>opt</h-></sub><h- data-h=sym_op>::</h-><h- data-h=sym_op>*</h->
<h- data-h=id>TT</h-><sub class=opt><h- data-h=id>opt</h-></sub><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
<h- data-h=id>TT</h-><sub class=opt><h- data-h=id>opt</h-></sub><h- data-h=sym_op>&lt;</h-><h- data-h=id>i</h-><h- data-h=sym_op>&gt;</h->
<h- data-h=id>TT</h-><sub class=opt><h- data-h=id>opt</h-></sub><h- data-h=sym_op>&lt;</h-><h- data-h=id>TT</h-><h- data-h=sym_op>&gt;</h->
<h- data-h=id>TT</h-><sub class=opt><h- data-h=id>opt</h-></sub><h- data-h=sym_op>&lt;</h-><h- data-h=id>VV</h-><h- data-h=sym_op>&gt;</h->
<h- data-h=id>TT</h-><sub class=opt><h- data-h=id>opt</h-></sub><h- data-h=sym_op>&lt;</h-><h- data-h=sym_op>&gt;</h-></code-block>

<p>where […]
</p></diff-block>

<p>Do <u>not</u> change <a href=https://eel.is/c++draft/temp.deduct.type#14>[temp.deduct.type] paragraph 14</a>; it is included here for reference.
</p>
<blockquote>
<p>The type of <tt->N</tt-> in the type <tt->T[N] is <tt->std::size_t</tt-></tt->.
</p>
<p>[<i>Example</i>: 
</p><code-block class=borderless>template&lt;typename T&gt; struct S;
template&lt;typename T, T n&gt; struct S&lt;int[n]&gt; {
  using Q = T;
};

using V = decltype(sizeof 0);
using V = S&lt;int[42]&gt;::Q;        // <f-serif>OK; <tt->T</tt-> was deduced as <tt->std::size_t</tt-> from the type <tt->int[42]</tt-></f-serif></code-block>
<p> — <i>end example</i>]
</p></blockquote>

<p>Immediately following <a href=https://eel.is/c++draft/temp.deduct.type#14>[temp.deduct.type] paragraph 14</a>, insert a new paragraph:
</p>
<ins-block>
<p>The type of <code><h- data-h=id>N</h-></code> in the type <code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-><h- data-h=sym_par>)</h-></code> is <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>size_t</h-></code>.
</p>
<p>[<i>Example</i>: 
</p><code-block class=borderless><h- data-h=kw>template</h-> <h- data-h=sym_op>&lt;</h-><h- data-h=kw>typename</h-> <h- data-h=id>T</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>n</h-><h- data-h=sym_op>&gt;</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>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>n</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->

<h- data-h=id>f</h-><h- data-h=sym_par>(</h-><h- data-h=num>0</h-><h- data-h=num_deco>wb</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; </h-><code><h- data-h=id>T</h-></code><h- data-h=cmt> was deduced as </h-><code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>size_t</h-></code><h- data-h=cmt> from an argument of type </h-><code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=num>1</h-><h- data-h=sym_par>)</h-></code></f-serif></code-block>
<p> — <i>end example</i>]
</p></ins-block>

<p>Change <a href=https://eel.is/c++draft/temp.deduct.type#20>[temp.deduct.type] paragraph 20</a> as follows:
</p>
<diff-block>
<p>If <code><h- data-h=id>P</h-></code> has a form that contains <code><h- data-h=sym_op>&lt;</h-><h- data-h=id>i</h-><h- data-h=sym_op>&gt;</h-></code>,
and if the type of <code><h- data-h=id>i</h-></code> differs from the type of the corresponding template parameter
of the template named by the enclosing <g-term>simple-template-id</g-term>
or <g-term>splice-specialization-specifier</g-term>, deduction fails.
If <code><h- data-h=id>P</h-></code> has a form that contains <code><h- data-h=sym_sqr>[</h-><h- data-h=id>i</h-><h- data-h=sym_sqr>]</h-></code>
<ins>or <code><h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>i</h-><h- data-h=sym_par>)</h-></code></ins>,
and if the type of <code><h- data-h=id>i</h-></code> is not an integral type, deduction fails.
If <code><h- data-h=id>P</h-></code> has a form that includes <code><h- data-h=kw>noexcept</h-><h- data-h=sym_par>(</h-><h- data-h=id>i</h-><h- data-h=sym_par>)</h-></code>
and the type of <code><h- data-h=id>i</h-></code> is not <code><h- data-h=kw_type>bool</h-></code>, deduction fails.
</p></diff-block>

<h4 id=cpp.predefined><a class=para href=#cpp%2epredefined></a>[cpp.predefined]</h4>

<p>Add a feature-test macro to the table in <a href=https://eel.is/c++draft/cpp.predefined>[cpp.predefined]</a> as follows:
</p>
<ins-block>
<code-block class=borderless><h- data-h=id>__cpp_bit_int</h-> <h- data-h=num>20</h-><h- data-h=num_deco>XXXXL</h-></code-block>
</ins-block>


<h3 id=library><a class=para href=#library></a>9.2. Library</h3>

<h4 id=version.syn><a class=para href=#version%2esyn></a>[version.syn]</h4>

<p>Add the following feature-test macro to <a href=https://eel.is/c++draft/version.syn>[version.syn]</a>:
</p>
<ins-block>
<code-block class=borderless><h- data-h=mac>#define __cpp_lib_bit_int                           20XXXXL</h-></code-block>
</ins-block>

<h4 id=cstdint.syn><a class=para href=#cstdint%2esyn></a>[cstdint.syn]</h4>

<p>In <a href=https://eel.is/c++draft/cstdint.syn>[cstdint.syn]</a>,
update the header synopsis as follows:
</p>
<diff-block>
<code-block class=borderless><h- data-h=kw>namespace</h-> <h- data-h=id>std</h-> <h- data-h=sym_brac>{</h->
  […]

  <h- data-h=kw>using</h-> <h- data-h=id_type>uintmax_t</h-> <h- data-h=sym_op>=</h-> <i><h- data-h=id>unsigned integer type</h-></i><h- data-h=sym_punc>;</h->
  <h- data-h=kw>using</h-> <h- data-h=id_type>uintptr_t</h-> <h- data-h=sym_op>=</h-> <i><h- data-h=id>unsigned integer type</h-></i><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>optional</h-></f-serif>

<ins>  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id_type>size_t</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>using</h-> <h- data-h=id>bit_int</h-> <h- data-h=sym_op>=</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id_type>size_t</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>using</h-> <h- data-h=id>bit_uint</h-> <h- data-h=sym_op>=</h-> <h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>_BitInt</h-><h- data-h=sym_par>(</h-><h- data-h=id>N</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></ins>
<h- data-h=sym_brac>}</h-></code-block>
</diff-block>

<p>Change <a href=https://eel.is/c++draft/cstdint.syn#2>[cstdint.syn] paragraph 2</a> as follows:
</p>
<diff-block>
<p>The header defines all types and macros the same as the C standard library header <tt->&lt;stdint.h&gt;</tt->.
<ins>None of the aliases name a bit-precise integer type.</ins>
The types denoted by <code><h- data-h=id_type>intmax_t</h-></code> and <code><h- data-h=id_type>uintmax_t</h-></code>
are not required to be able to represent all values of
<ins>bit-precise integer types or of</ins>
extended integer types wider than
<code><ins>“</ins><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <ins><h- data-h=kw_type>int</h-></ins><ins>”</ins></code> and
<code><ins>“</ins><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <ins><h- data-h=kw_type>int</h-></ins><ins>”</ins></code>,
respectively.
</p></diff-block>

<p>Change <a href=https://eel.is/c++draft/cstdint.syn#3>[cstdint.syn] paragraph 3</a> as follows:
</p>
<diff-block>
<p>All types that use the placeholder <tt-><i><h- data-h=id>N</h-></i></tt->
are optional when <tt-><i><h- data-h=id>N</h-></i></tt->
is not <code><h- data-h=num>8</h-></code>, <code><h- data-h=num>16</h-></code>, <code><h- data-h=num>32</h-></code>, or <code><h- data-h=num>64</h-></code>.
The exact-width types
<code><h- data-h=id_type>int</h-><i><h- data-h=id_type>N</h-></i><h- data-h=id_type>_t</h-></code> and <code><h- data-h=id_type>uint</h-><i><h- data-h=id_type>N</h-></i><h- data-h=id_type>_t</h-></code>
for <tt-><i><h- data-h=id>N</h-></i></tt-> = <code><h- data-h=num>8</h-></code>, <code><h- data-h=num>16</h-></code>, <code><h- data-h=num>32</h-></code>, and <code><h- data-h=num>64</h-></code>
are also optional;
however, if an implementation defines integer types
<ins>other than bit-precise integer types</ins>
with the corresponding width and no padding bits,
it defines the corresponding <g-term>typedef-name</g-term>s.
Each of the macros listed in this subclause
is defined if and only if
the implementation defines the corresponding <g-term>typedef-name</g-term>.
<br/>[<i>Note</i>: 
The macros <code><h- data-h=id>INT</h-><i><h- data-h=id>N</h-></i><h- data-h=id>_C</h-></code> and <code><h- data-h=id>UINT</h-><i><h- data-h=id>N</h-></i><h- data-h=id>_C</h-></code>
correspond to the <g-term>typedef-name</g-term>s
<code><h- data-h=id_type>int_least</h-><i><h- data-h=id_type>N</h-></i><h- data-h=id_type>_t</h-></code> and <code><h- data-h=id_type>uint_least</h-><i><h- data-h=id_type>N</h-></i><h- data-h=id_type>_t</h-></code>,
respectively.
 — <i>end note</i>]
</p></diff-block>

<h4 id=climits.syn><a class=para href=#climits%2esyn></a>[climits.syn]</h4>

<p>In <a href=https://eel.is/c++draft/climits.syn>[climits.syn]</a>,
add a new line below the definition of <code><h- data-h=mac>ULLONG_WIDTH</h-></code>:
</p>
<ins-block>
<code-block class=borderless><h- data-h=mac>#define BITINT_MAXWIDTH </h-><i><h- data-h=id>see below</h-></i></code-block>
</ins-block>

<p>Change the synopsis in <a href=https://eel.is/c++draft/climits.syn#1>[climits.syn] paragraph 1</a> as follows:
</p>
<diff-block>
<p>The header <tt->&lt;climits&gt;</tt-> defines all macros
the same as the C standard library header <tt->limits.h</tt-><del>,
except that it does not define the macro <code><h- data-h=id>BITINT_MAXWIDTH</h-></code></del>.
</p></diff-block>

<h4 id=stdbit.h.syn><a class=para href=#stdbit%2eh%2esyn></a>[stdbit.h.syn]</h4>

<p>Change <a href=https://eel.is/c++draft/stdbit.h.syn#2>[stdbit.h.syn] paragraph 2</a> as follows:
</p>
<diff-block>
<p><i>Mandates</i>:
<code><h- data-h=id>T</h-></code> is <del>an unsigned integer type</del>
</p><ul>
  <li><ins>a standard unsigned integer type,</ins></li>
  <li><ins>an extended unsigned integer type, or</ins></li>
  <li>
    <ins>a bit-precise unsigned integer type whose width matches
    a standard or extended integer type</ins>.
  </li>
</ul>
</diff-block>

<h4 id=range.iota.view><a class=para href=#range%2eiota%2eview></a>[range.iota.view]</h4>

<note-block><p><intro-></intro-> See <a href=#preventing-iota-view-abi-break>§5.3. Preventing <tt->ranges::iota_view</tt-> ABI break</a>.</p></note-block>

<p>Change <a href=https://eel.is/c++draft/range.iota.view#1>[range.iota.view] paragraph 1</a> as follows:
</p>
<diff-block>
<p>Let <code><i><h- data-h=id>IOTA-DIFF-T</h-></i><h- data-h=sym_par>(</h-><h- data-h=id>W</h-><h- data-h=sym_par>)</h-></code> be defined as follows:
</p>
<ul>
  <li>
    If <code><h- data-h=id>W</h-></code> is not an integral type,
    or if it is an integral type and <code><h- data-h=kw>sizeof</h-><h- data-h=sym_par>(</h-><h- data-h=id_type>iter_difference_t</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>W</h-><h- data-h=sym_op>&gt;</h-><h- data-h=sym_par>)</h-></code> is
    greater than <code><h- data-h=kw>sizeof</h-><h- data-h=sym_par>(</h-><h- data-h=id>W</h-><h- data-h=sym_par>)</h-></code>,
    then <code><i><h- data-h=id>IOTA-DIFF-T</h-></i><h- data-h=sym_par>(</h-><h- data-h=id>W</h-><h- data-h=sym_par>)</h-></code> denotes <code><h- data-h=id_type>iter_difference_t</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>W</h-><h- data-h=sym_op>&gt;</h-></code>.
  </li>
  <li>
    Otherwise, <code><i><h- data-h=id>IOTA-DIFF-T</h-></i><h- data-h=sym_par>(</h-><h- data-h=id>W</h-><h- data-h=sym_par>)</h-></code>
    is a <ins>standard</ins> signed integer type of width greater than the width of <code><h- data-h=id>W</h-></code>
    if such a type exists.
  </li>
  <li>
    Otherwise, <code><i><h- data-h=id>IOTA-DIFF-T</h-></i><h- data-h=sym_par>(</h-><h- data-h=id>W</h-><h- data-h=sym_par>)</h-></code>
    is an unspecified signed-integer-like (<a href=https://eel.is/c++draft/iterator.concept.winc>[iterator.concept.winc]</a>) type
    of width not less than the width of <code><h- data-h=id>W</h-></code>.
  </li>
</ul>
</diff-block>

<h4 id=alg.foreach><a class=para href=#alg%2eforeach></a>[alg.foreach]</h4>

<p>Change <a href=https://eel.is/c++draft/alg.foreach#lib:for_each_n>[alg.foreach] <tt->for_each_n</tt-></a> as follows:
</p>
<diff-block>
<code-block class=borderless><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>InputIterator</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>class</h-> <h- data-h=id>Size</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>class</h-> <h- data-h=id>Function</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>InputIterator</h-> <h- data-h=id>for_each_n</h-><h- data-h=sym_par>(</h-><h- data-h=id>InputIterator</h-> <h- data-h=id>first</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>Size</h-> <h- data-h=id>n</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>Function</h-> <h- data-h=id>f</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<div class=indent>
<p><i>Mandates</i>:
The type <code><h- data-h=id>Size</h-></code> is convertible to an integral type
<ins>other than a bit-precise integer type</ins>
(<a href=https://eel.is/c++draft/conv.integral>[conv.integral]</a>, <a href=https://eel.is/c++draft/class.conv>[class.conv]</a>).
</p>
<p>[…]
</p></div>

<code-block class=borderless><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>ExecutionPolicy</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>class</h-> <h- data-h=id>ForwardIterator</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>class</h-> <h- data-h=id>Size</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>class</h-> <h- data-h=id>Function</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=id>ForwardIterator</h-> <h- data-h=id>for_each_n</h-><h- data-h=sym_par>(</h-><h- data-h=id>ExecutionPolicy</h-><h- data-h=sym_op>&amp;&amp;</h-> <h- data-h=id>exec</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>ForwardIterator</h-> <h- data-h=id>first</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>Size</h-> <h- data-h=id>n</h-><h- data-h=sym_punc>,</h->
                             <h- data-h=id>Function</h-> <h- data-h=id>f</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<div class=indent>
<p><i>Mandates</i>:
The type <code><h- data-h=id>Size</h-></code> is convertible to an integral type
<ins>other than a bit-precise integer type</ins>
(<a href=https://eel.is/c++draft/conv.integral>[conv.integral]</a>, <a href=https://eel.is/c++draft/class.conv>[class.conv]</a>).
</p>
<p>[…]
</p></div>
</diff-block>

<note-block><p><intro-></intro-> 
Implementing this requirement for bit-precise integer types is generally impossible,
barring compiler magic.
The libc++ implementation is done by calling an overload in the set:
</p>
<code-block><h- data-h=kw_type>int</h-> <h- data-h=id>__convert_to_integral</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>__val</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h-> <h- data-h=kw_ctrl>return</h-> <h- data-h=id>__val</h-><h- data-h=sym_punc>;</h-> <h- data-h=sym_brac>}</h->
<h- data-h=kw_type>unsigned</h-> <h- data-h=id>__convert_to_integral</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>unsigned</h-> <h- data-h=id>__val</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h-> <h- data-h=kw_ctrl>return</h-> <h- data-h=id>__val</h-><h- data-h=sym_punc>;</h-> <h- data-h=sym_brac>}</h-></code-block>

<p>It is not reasonable to expect millions of additional overloads,
and a template that can handle bit-precise integers in bulk could not interoperate with
user-defined conversion function templates.
</p></note-block>

<h4 id=alg.search><a class=para href=#alg%2esearch></a>[alg.search]</h4>

<p>Change <a href=https://eel.is/c++draft/alg.search#5>[alg.search] paragraph 5</a> as follows:
</p>
<diff-block>
<p><i>Mandates</i>:
The type <code><h- data-h=id>Size</h-></code> is convertible to an integral type
<ins>other than a bit-precise integer type</ins>
(<a href=https://eel.is/c++draft/conv.integral>[conv.integral]</a>, <a href=https://eel.is/c++draft/class.conv>[class.conv]</a>).
</p></diff-block>

<h4 id=alg.copy><a class=para href=#alg%2ecopy></a>[alg.copy]</h4>

<p>Change <a href=https://eel.is/c++draft/alg.copy#15>[alg.copy] paragraph 15</a> as follows:
</p>
<diff-block>
<p><i>Mandates</i>:
The type <code><h- data-h=id>Size</h-></code> is convertible to an integral type
<ins>other than a bit-precise integer type</ins>
(<a href=https://eel.is/c++draft/conv.integral>[conv.integral]</a>, <a href=https://eel.is/c++draft/class.conv>[class.conv]</a>).
</p></diff-block>

<h4 id=alg.fill><a class=para href=#alg%2efill></a>[alg.fill]</h4>

<p>Change <a href=https://eel.is/c++draft/alg.fill#2>[alg.fill] paragraph 2</a> as follows:
</p>
<diff-block>
<p><i>Mandates</i>:
The expression <code><h- data-h=id>value</h-></code> is writable (<a href=https://eel.is/c++draft/iterator.requirements.general>[iterator.requirements.general]</a>)
to the output iterator.
The type <code><h- data-h=id>Size</h-></code> is convertible to an integral type
<ins>other than a bit-precise integer type</ins>
(<a href=https://eel.is/c++draft/conv.integral>[conv.integral]</a>, <a href=https://eel.is/c++draft/class.conv>[class.conv]</a>).
</p></diff-block>

<h4 id=alg.generate><a class=para href=#alg%2egenerate></a>[alg.generate]</h4>

<p>Change <a href=https://eel.is/c++draft/alg.generate#2>[alg.generate] paragraph 2</a> as follows:
</p>
<diff-block>
<p><i>Mandates</i>:
<code><h- data-h=id>Size</h-></code> is convertible to an integral type
<ins>other than a bit-precise integer type</ins>
(<a href=https://eel.is/c++draft/conv.integral>[conv.integral]</a>, <a href=https://eel.is/c++draft/class.conv>[class.conv]</a>).
</p></diff-block>

<h4 id=charconv.syn><a class=para href=#charconv%2esyn></a>[charconv.syn]</h4>

<p>Change <a href=https://eel.is/c++draft/charconv.syn#1>[charconv.syn] paragraph 1</a> as follows:
</p>
<diff-block>
<p>When a function is specified with a type placeholder of <code><i><h- data-h=id>integer-type</h-></i></code>,
the implementation provides overloads for <code><h- data-h=kw_type>char</h-></code>
and all <del>cv-unqualified signed and unsigned integer types</del>
<ins>standard and extended integer types</ins>
in lieu of <code><i><h- data-h=id>integer-type</h-></i></code>.
When a function is specified with a type placeholder of <code><i><h- data-h=id>floating-point-type</h-></i></code>,
the implementation provides overloads for all
cv-unqualified floating-point types (<a href=https://eel.is/c++draft/basic.fundamental>[basic.fundamental]</a>)
in lieu of <code><i><h- data-h=id>floating-point-type</h-></i></code>.
</p>
<code-block class=borderless><h- data-h=kw>namespace</h-> <h- data-h=id>std</h-> <h- data-h=sym_brac>{</h->
  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>floating-point format for primitive numerical conversion</h-></f-serif>
  <h- data-h=kw>enum</h-> <h- data-h=kw>class</h-> <h- data-h=id>chars_format</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=id>scientific</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>unspecified</h-><h- data-h=sym_punc>,</h->
    <h- data-h=id>fixed</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>unspecified</h-><h- data-h=sym_punc>,</h->
    <h- data-h=id>hex</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>unspecified</h-><h- data-h=sym_punc>,</h->
    <h- data-h=id>general</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>fixed</h-> <h- data-h=sym_op>|</h-> <h- data-h=id>scientific</h->
  <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->

  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>[charconv.to.chars], primitive numerical output conversion</h-></f-serif>
  <h- data-h=kw>struct</h-> <h- data-h=id>to_chars_result</h-> <h- data-h=sym_brac>{</h->                                              <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>freestanding</h-></f-serif>
    <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>ptr</h-><h- data-h=sym_punc>;</h->
    <h- data-h=id>errc</h-> <h- data-h=id>ec</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw>friend</h-> <h- data-h=kw_type>bool</h-> <h- data-h=kw>operator</h-><h- data-h=sym_op>==</h-><h- data-h=sym_par>(</h-><h- data-h=kw>const</h-> <h- data-h=id>to_chars_result</h-><h- data-h=sym_op>&amp;</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>const</h-> <h- data-h=id>to_chars_result</h-><h- data-h=sym_op>&amp;</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>=</h-> <h- data-h=kw>default</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=kw>explicit</h-> <h- data-h=kw>operator</h-> <h- data-h=kw_type>bool</h-><h- data-h=sym_par>(</h-><h- data-h=sym_par>)</h-> <h- data-h=kw>const</h-> <h- data-h=kw>noexcept</h-> <h- data-h=sym_brac>{</h-> <h- data-h=kw_ctrl>return</h-> <h- data-h=id>ec</h-> <h- data-h=sym_op>==</h-> <h- data-h=id>errc</h-><h- data-h=sym_brac>{</h-><h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h-> <h- data-h=sym_brac>}</h->
  <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->

  <h- data-h=kw>constexpr</h-> <h- data-h=id>to_chars_result</h-> <h- data-h=id>to_chars</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>first</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>last</h-><h- data-h=sym_punc>,</h->           <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>freestanding</h-></f-serif>
                                     <i><h- data-h=id>integer-type</h-></i> <h- data-h=id>value</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>base</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>10</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<ins>  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>to_chars_result</h-> <h- data-h=id>to_chars</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>first</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>last</h-><h- data-h=sym_punc>,</h->         <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>freestanding</h-></f-serif>
                                       <h- data-h=id>T</h-> <h- data-h=id>value</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>base</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>10</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></ins>
  <h- data-h=id>to_chars_result</h-> <h- data-h=id>to_chars</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>first</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>last</h-><h- data-h=sym_punc>,</h->                     <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>freestanding</h-></f-serif>
                           <h- data-h=kw_type>bool</h-> <h- data-h=id>value</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>base</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>10</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=id>to_chars_result</h-> <h- data-h=id>to_chars</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>first</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>last</h-><h- data-h=sym_punc>,</h->                     <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>freestanding-deleted</h-></f-serif>
                           <i><h- data-h=id>floating-point-type</h-></i> <h- data-h=id>value</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id>to_chars_result</h-> <h- data-h=id>to_chars</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>first</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>last</h-><h- data-h=sym_punc>,</h->                     <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>freestanding-deleted</h-></f-serif>
                           <i><h- data-h=id>floating-point-type</h-></i> <h- data-h=id>value</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>chars_format</h-> <h- data-h=id>fmt</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id>to_chars_result</h-> <h- data-h=id>to_chars</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>first</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>last</h-><h- data-h=sym_punc>,</h->                     <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>freestanding-deleted</h-></f-serif>
                           <i><h- data-h=id>floating-point-type</h-></i> <h- data-h=id>value</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>chars_format</h-> <h- data-h=id>fmt</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>precision</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>[charconv.from.chars], primitive numerical input conversion</h-></f-serif>
  <h- data-h=kw>struct</h-> <h- data-h=id>from_chars_result</h-> <h- data-h=sym_brac>{</h->                                            <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>freestanding</h-></f-serif>
    <h- data-h=kw>const</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>ptr</h-><h- data-h=sym_punc>;</h->
    <h- data-h=id>errc</h-> <h- data-h=id>ec</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw>friend</h-> <h- data-h=kw_type>bool</h-> <h- data-h=kw>operator</h-><h- data-h=sym_op>==</h-><h- data-h=sym_par>(</h-><h- data-h=kw>const</h-> <h- data-h=id>from_chars_result</h-><h- data-h=sym_op>&amp;</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>const</h-> <h- data-h=id>from_chars_result</h-><h- data-h=sym_op>&amp;</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>=</h-> <h- data-h=kw>default</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=kw>explicit</h-> <h- data-h=kw>operator</h-> <h- data-h=kw_type>bool</h-><h- data-h=sym_par>(</h-><h- data-h=sym_par>)</h-> <h- data-h=kw>const</h-> <h- data-h=kw>noexcept</h-> <h- data-h=sym_brac>{</h-> <h- data-h=kw_ctrl>return</h-> <h- data-h=id>ec</h-> <h- data-h=sym_op>==</h-> <h- data-h=id>errc</h-><h- data-h=sym_brac>{</h-><h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h-> <h- data-h=sym_brac>}</h->
  <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->

  <h- data-h=kw>constexpr</h-> <h- data-h=id>from_chars_result</h-> <h- data-h=id>from_chars</h-><h- data-h=sym_par>(</h-><h- data-h=kw>const</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>first</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>const</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>last</h-><h- data-h=sym_punc>,</h->   <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>freestanding</h-></f-serif>
                                         <i><h- data-h=id>integer-type</h-></i><h- data-h=sym_op>&amp;</h-> <h- data-h=id>value</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>base</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>10</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<ins>  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>from_chars_result</h-> <h- data-h=id>from_chars</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>first</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>last</h-><h- data-h=sym_punc>,</h->         <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>freestanding</h-></f-serif>
                                           <h- data-h=id>T</h-><h- data-h=sym_op>&amp;</h-> <h- data-h=id>value</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>base</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>10</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></ins>

  <h- data-h=id>from_chars_result</h-> <h- data-h=id>from_chars</h-><h- data-h=sym_par>(</h-><h- data-h=kw>const</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>first</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>const</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>last</h-><h- data-h=sym_punc>,</h->     <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>freestanding-deleted</h-></f-serif>
                               <i><h- data-h=id>floating-point-type</h-></i><h- data-h=sym_op>&amp;</h-> <h- data-h=id>value</h-><h- data-h=sym_punc>,</h->
                               <h- data-h=id>chars_format</h-> <h- data-h=id>fmt</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>chars_format</h-><h- data-h=sym_op>::</h-><h- data-h=id>general</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-></code-block>
</diff-block>

<h4 id=charconv.to.chars><a class=para href=#charconv%2eto%2echars></a>[charconv.to.chars]</h4>

<p>Change <a href=https://eel.is/c++draft/charconv.to.chars>[charconv.to.chars]</a> as follows:
</p>
<diff-block>
<p>[…]</p>

<code-block class=borderless><h- data-h=kw>constexpr</h-> <h- data-h=id>to_chars_result</h-> <h- data-h=id>to_chars</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>first</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>last</h-><h- data-h=sym_punc>,</h-> <i><h- data-h=id>integer-type</h-></i> <h- data-h=id>value</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>base</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>10</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<ins><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>to_chars_result</h-> <h- data-h=id>to_chars</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>first</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>last</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>value</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>base</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>10</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></ins></code-block>

<div class=indent>
<p><ins><i>Constraints</i>:
<code><h- data-h=id>T</h-></code> is a bit-precise integer type.</ins></p>

<p><i>Preconditions</i>:
<code><h- data-h=id>base</h-></code> has a value between 2 and 36 (inclusive).
</p></div>

<p>[…]
</p></diff-block>

<h4 id=charconv.from.chars><a class=para href=#charconv%2efrom%2echars></a>[charconv.from.chars]</h4>

<p>Change <a href=https://eel.is/c++draft/charconv.from.chars>[charconv.from.chars]</a> as follows:
</p>
<diff-block>
<p>[…]</p>

<code-block class=borderless><h- data-h=kw>constexpr</h-> <h- data-h=id>from_chars_result</h-> <h- data-h=id>from_chars</h-><h- data-h=sym_par>(</h-><h- data-h=kw>const</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>first</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>const</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>last</h-><h- data-h=sym_punc>,</h->
                                       <i><h- data-h=id>integer-type</h-></i><h- data-h=sym_op>&amp;</h-> <h- data-h=id>value</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>base</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>10</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<ins><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>from_chars_result</h-> <h- data-h=id>from_chars</h-><h- data-h=sym_par>(</h-><h- data-h=kw>const</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>first</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>const</h-> <h- data-h=kw_type>char</h-><h- data-h=sym_op>*</h-> <h- data-h=id>last</h-><h- data-h=sym_punc>,</h->
                                         <h- data-h=id>T</h-><h- data-h=sym_op>&amp;</h-> <h- data-h=id>value</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>base</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>10</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></ins></code-block>

<div class=indent>
<p><ins><i>Constraints</i>:
<code><h- data-h=id>T</h-></code> is a bit-precise integer type.</ins></p>

<p><i>Preconditions</i>:
<code><h- data-h=id>base</h-></code> has a value between 2 and 36 (inclusive).
</p></div>

<p>[…]
</p></diff-block>

<h4 id=string.syn><a class=para href=#string%2esyn></a>[string.syn]</h4>

<p>Change <a href=https://eel.is/c++draft/string.syn>[string.syn]</a> as follows:
</p>
<diff-block>
<code-block class=borderless><h- data-h=kw>namespace</h-> <h- data-h=id>std</h-> <h- data-h=sym_brac>{</h->
  […]

  <h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>unsigned</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>long</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>float</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>double</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>long</h-> <h- data-h=kw_type>double</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<ins>  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></ins>

  […]

  <h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>unsigned</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>long</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>float</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>double</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>long</h-> <h- data-h=kw_type>double</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<ins>  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></ins>

  […]
<h- data-h=sym_brac>}</h-></code-block>
</diff-block>

<p>If the existing overloads for integral types
have been made <code><h- data-h=kw>constexpr</h-></code> through <a href="https://wg21%2elink/p3438r0">[P3438R0]</a> or a subsequent paper,
additionally make the following changes:
</p>
<diff-block>
<code-block class=borderless>[…]
<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <ins><h- data-h=kw>constexpr</h-></ins> <h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
[…]
<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <ins><h- data-h=kw>constexpr</h-></ins> <h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
[…]</code-block>
</diff-block>

<h4 id=string.conversions><a class=para href=#string%2econversions></a>[string.conversions]</h4>

<p>Change <a href=https://eel.is/c++draft/string.conversions>[string.conversions]</a> as follows:
</p>
<diff-block>
<p>[…]</p>

<code-block class=borderless><h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>unsigned</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>long</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>float</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>double</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>long</h-> <h- data-h=kw_type>double</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<ins><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></ins></code-block>

<div class=indent>
<p><ins><i>Constraints</i>:
<code><h- data-h=id>T</h-></code> is a bit-precise or extended integer type.</ins></p>

<p><i>Returns</i>:
<code><h- data-h=id>format</h-><h- data-h=sym_par>(</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=id>val</h-><h- data-h=sym_par>)</h-></code>.
</p></div>

<p>[…]</p>

<code-block class=borderless><h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>unsigned</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>long</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>float</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>double</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>long</h-> <h- data-h=kw_type>double</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<ins><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></ins></code-block>

<div class=indent>
<p><ins><i>Constraints</i>:
<code><h- data-h=id>T</h-></code> is a bit-precise or extended integer type.</ins></p>

<p><i>Returns</i>:
<code><h- data-h=id>format</h-><h- data-h=sym_par>(</h-><h- data-h=str_deco>L</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=id>val</h-><h- data-h=sym_par>)</h-></code>.
</p></div>

<p>[…]
</p></diff-block>

<p>If the existing overloads for integral types
have been made <code><h- data-h=kw>constexpr</h-></code> through <a href="https://wg21%2elink/p3438r0">[P3438R0]</a> or a subsequent paper,
additionally make the following changes:
</p>
<diff-block>
<code-block class=borderless>[…]
<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <ins><h- data-h=kw>constexpr</h-></ins> <h- data-h=id>string</h-> <h- data-h=id>to_string</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
[…]
<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <ins><h- data-h=kw>constexpr</h-></ins> <h- data-h=id>wstring</h-> <h- data-h=id>to_wstring</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>val</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
[…]</code-block>
</diff-block>

<h4 id=cmath.syn><a class=para href=#cmath%2esyn></a>[cmath.syn]</h4>

<note-block><p><intro-></intro-> 
<a href=https://eel.is/c++draft/cmath.syn#3>[cmath.syn] paragraph 3</a> is deliberately not changed,
meaning that <code><h- data-h=id>bit_int</h-></code> may be passed to e.g. <code><h- data-h=id>sqrt</h-></code>.
See <a href=#bitint-cmath>§5.6. Using bit-precise integers in <tt->&lt;cmath&gt;</tt-> functions</a>.
</p></note-block>

<p>In <a href=https://eel.is/c++draft/cmath.syn>[cmath.syn]</a>, change the synopsis as follows:
</p>
<diff-block>
<code-block class=borderless><h- data-h=kw>constexpr</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>j</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>freestanding</h-></f-serif>
<h- data-h=kw>constexpr</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>j</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>freestanding</h-></f-serif>
<h- data-h=kw>constexpr</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>j</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>freestanding</h-></f-serif>
<ins><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id_type>size_t</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=kw>constexpr</h-> <h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>j</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>freestanding</h-></f-serif></ins>
<h- data-h=kw>constexpr</h-> <i><h- data-h=id>floating-point-type</h-></i> <h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><i><h- data-h=id>floating-point-type</h-></i> <h- data-h=id>j</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>freestanding</h-></f-serif></code-block>
</diff-block>



<h4 id=c.math.abs><a class=para href=#c%2emath%2eabs></a>[c.math.abs]</h4>

<note-block><p><intro-></intro-> 
See <a href=#bitint-abs>§5.5. New <tt->abs</tt-> overload</a>.
</p></note-block>

<p>Change <a href=https://eel.is/c++draft/c.math.abs>[c.math.abs]</a> as follows:
</p>
<diff-block>
<code-block class=borderless><h- data-h=kw>constexpr</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>j</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw>constexpr</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>j</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw>constexpr</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>j</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<ins><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id_type>size_t</h-> <h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=kw>constexpr</h-> <h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=id>bit_int</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>N</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>j</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></ins></code-block>

<p><del><i>Effects</i>:
These functions have the semantics specified in the C standard library for the functions
<code><h- data-h=id>abs</h-></code>, <code><h- data-h=id>labs</h-></code>, and <code><h- data-h=id>llabs</h-></code>, respectively.</del></p>

<p><del><i>Remarks</i>:
If <code><h- data-h=id>abs</h-></code> is called with an argument of type <code><h- data-h=id>X</h-></code>
for which <code><h- data-h=id>is_unsigned_v</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>X</h-><h- data-h=sym_op>&gt;</h-></code> is <code><h- data-h=bool>true</h-></code>
and if <code><h- data-h=id>X</h-></code> cannot be converted to <code><h- data-h=kw_type>int</h-></code> by integral promotion,
the program is ill-formed.
<br/>[<i>Note</i>: 
Allowing arguments that can be promoted to <code><h- data-h=kw_type>int</h-></code> provides compatibility with C.
 — <i>end note</i>]</del></p>

<p><ins><i>Effects</i>:
Equivalent to <code><h- data-h=id>j</h-> <h- data-h=sym_op>&gt;=</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>?</h-> <h- data-h=id>j</h-> <h- data-h=sym_punc>:</h-> <h- data-h=sym_op>-</h-><h- data-h=id>j</h-></code>.
<br/>[<i>Note</i>: The behavior is undefined if <code><h- data-h=id>j</h-></code>
has the lowest possible integer value of its type (<a href=https://eel.is/c++draft/expr.pre>[expr.pre]</a>). — <i>end note</i>]</ins>
</p></diff-block>

<note-block><p><intro-></intro-> 
Specifying the undefined behavior as a <i>Preconditions</i> specification
would be worse because it may cause library UB during constant evaluation.
</p>
<p>The <i>Effects</i> specification needs to be altered because <code><h- data-h=id>abs</h-></code>
for bit-precise integers is a novel invention with no C counterpart.
It also seems like unnecessary indirection to refer to another language standard
for a single expression.
</p>
<p>The <i>Remarks</i> specification is removed
because is a usage tutorial and history lesson;
it does not say anything about what <code><h- data-h=id>abs</h-></code> does.
The specification is also factually wrong.
Just because an attempt is made to call <code><h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=num>0</h-><h- data-h=num_deco>u</h-><h- data-h=sym_par>)</h-></code> and the overloads above
don't handle it,
doesn't mean that the user doesn't have their own
<code><h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>unsigned</h-><h- data-h=sym_par>)</h-></code> overload.
In that event, the program is not ill-formed;
overload resolution simply doesn't select one of these functions.
</p></note-block>

<h4 id=simd.general><a class=para href=#simd%2egeneral></a>[simd.general]</h4>

<p>Change <a href=https://eel.is/c++draft/simd.general#2>[simd.general] paragraph 2</a> as follows:
</p>
<diff-block>
<p>The set of <dfn>vectorizable types</dfn> comprises
</p>
<ul>
  <li>
    all standard integer types,
    character types,
    and the types <code><h- data-h=kw_type>float</h-></code> and <code><h- data-h=kw_type>double</h-></code> (<a href=https://eel.is/c++draft/basic.fundamental>[basic.fundamental]</a>);
  </li>
  <li>
    <ins>any bit-precise integer type
    whose width matches a standard integer type;</ins>
  </li>
  <li>
    <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>float16_t</h-></code>, <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>float32_t</h-></code>, and <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>float64_t</h-></code>
    if defined (<a href=https://eel.is/c++draft/basic.extended.fp>[basic.extended.fp]</a>); and
  </li>
  <li>
    <code><h- data-h=kw>complex</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-></code> where <code><h- data-h=id>T</h-></code> is a vectorizable floating-point type.
  </li>
</ul>
</diff-block>

<h4 id=numerics.c.ckdint><a class=para href=#numerics%2ec%2eckdint></a>[numerics.c.ckdint]</h4>

<p>Change <a href=https://eel.is/c++draft/numerics.c.ckdint>[numerics.c.ckdint]</a> as follows:
</p>
<diff-block>
<code-block class=borderless><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>type1</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>class</h-> <h- data-h=id>type2</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>class</h-> <h- data-h=id>type3</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw_type>bool</h-> <h- data-h=id>ckd_add</h-><h- data-h=sym_par>(</h-><h- data-h=id>type1</h-><h- data-h=sym_op>*</h-> <h- data-h=id>result</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>type2</h-> <h- data-h=id>a</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>type3</h-> <h- data-h=id>b</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>type1</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>class</h-> <h- data-h=id>type2</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>class</h-> <h- data-h=id>type3</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw_type>bool</h-> <h- data-h=id>ckd_sub</h-><h- data-h=sym_par>(</h-><h- data-h=id>type1</h-><h- data-h=sym_op>*</h-> <h- data-h=id>result</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>type2</h-> <h- data-h=id>a</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>type3</h-> <h- data-h=id>b</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>type1</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>class</h-> <h- data-h=id>type2</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>class</h-> <h- data-h=id>type3</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw_type>bool</h-> <h- data-h=id>ckd_mul</h-><h- data-h=sym_par>(</h-><h- data-h=id>type1</h-><h- data-h=sym_op>*</h-> <h- data-h=id>result</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>type2</h-> <h- data-h=id>a</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>type3</h-> <h- data-h=id>b</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<p><i>Mandates</i>:
<ins><code><h- data-h=id>type1</h-></code> is a signed or unsigned integer type.</ins>
Each of the types <del><code><h- data-h=id>type1</h-></code>,</del>
<code><h- data-h=id>type2</h-></code><del>,</del> and <code><h- data-h=id>type3</h-></code>
is a <del>cv-unqualified</del> signed or unsigned integer type
<ins>other than a bit-precise integer type</ins>.
</p>
<p><i>Remarks</i>:
Each function template has the same semantics
as the corresponding type-generic macro with the same name
specified in ISO/IEC 9899:2024, 7.20.
</p></diff-block>

<note-block><p><intro-></intro-> 
This matches the restrictions in <a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg14/www/docs/n3550%2epdf">[N3550]</a>, 7.20 "Checked Integer Arithmetic".
"cv-unqualified" is struck because it is redundant.
</p></note-block>

<h4 id=atomics.ref.int><a class=para href=#atomics%2eref%2eint></a>[atomics.ref.int]</h4>

<p>Do <u>not</u> change <a href=https://eel.is/c++draft/atomics.ref.int#1>[atomics.ref.int] paragraph 1</a>;
it is provided here for reference:
</p>
<blockquote>
<p>There are specializations of the <code><h- data-h=id>atomic_ref</h-></code> class template
for all integral types except <i><h- data-h=id>cv</h-></i> <code><h- data-h=kw_type>bool</h-></code>.
For each such type <code><i><h- data-h=id>integral-type</h-></i></code>,
the specialization <code><h- data-h=id>atomic_ref</h-><h- data-h=sym_op>&lt;</h-><i><h- data-h=id>integral-type</h-></i><h- data-h=sym_op>&gt;</h-></code>
provides additional atomic operations
appropriate to integral types.
</p></blockquote>

<h4 id=atomics.types.int><a class=para href=#atomics%2etypes%2eint></a>[atomics.types.int]</h4>

<p>Change <a href=https://eel.is/c++draft/atomics.types.int#1>[atomics.types.int] paragraph 1</a> as follows:
</p>
<diff-block>
<p>There are specializations of the <code><h- data-h=id>atomic</h-></code> class template for
<del>the integral types
<code><h- data-h=kw_type>char</h-></code>,
<code><h- data-h=kw_type>signed</h-> <h- data-h=kw_type>char</h-></code>,
<code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>char</h-></code>,
<code><h- data-h=kw_type>short</h-></code>,
<code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>short</h-></code>,
<code><h- data-h=kw_type>int</h-></code>,
<code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>int</h-></code>,
<code><h- data-h=kw_type>long</h-></code>,
<code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-></code>,
<code><h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-></code>,
<code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-></code>,
<code><h- data-h=kw_type>char8_t</h-></code>,
<code><h- data-h=kw_type>char16_t</h-></code>,
<code><h- data-h=kw_type>char32_t</h-></code>,
<code><h- data-h=kw_type>wchar_t</h-></code>,</del>
<ins>standard integer types,
bit-precise integer types,
character types,</ins>
and any other types needed by the typedefs
in the header <tt->&lt;cstdint&gt;</tt-> (<a href=https://eel.is/c++draft/cstdint.syn>[cstdint.syn]</a>).
For each such type <code><i><h- data-h=id>integral-type</h-></i></code>,
the specialization <code><h- data-h=id>atomic</h-><h- data-h=sym_op>&lt;</h-><i><h- data-h=id>integral-type</h-></i><h- data-h=sym_op>&gt;</h-></code>
provides additional atomic operations
appropriate to integral types.
</p>
<p>[<i>Note</i>: 
The specialization <code><h- data-h=id>atomic</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>bool</h-><h- data-h=sym_op>&gt;</h-></code>
uses the primary template (<a href=https://eel.is/c++draft/atomics.types.generic>[atomics.types.generic]</a>).
 — <i>end note</i>]
</p></diff-block>

<h2 id=acknowledgements><a class=para href=#acknowledgements></a>10. Acknowledgements</h2>

<p>I thank Jens Maurer and Christof Meerwald
for reviewing and correcting the proposal's wording.
</p>
<p>I thank Erich Keane and other LLVM contributors
for implementing most of the proposed core changes in Clang's C++ frontend,
giving this paper years worth of implementation experience in a major compiler
without any effort by the author.
</p>
<p>I thank
Erich Keane,
Bill Seymour,
Howard Hinnant,
JeanHeyd Meneide,
Lénárd Szolnoki,
Brian Bi,
Peter Dimov,
Aaron Ballman,
Pete Becker,
Jens Maurer,
Matthias Kretz,
Jonathan Wakely,
Jeff Garland,
Ville Voutilainen,
Peter Dimov,
Luigi Ghiron,
and <em>many</em> others for providing early feedback on this paper,
prior papers such as <a href="https://wg21%2elink/p3639r0">[P3639R0]</a>, and
the discussion surrounding bit-precise integers as a whole.
The paper would not be where it is today without <em>hundreds</em>
of messages worth of valuable feedback.
</p>
<h2 id=references><a class=para href=#references></a>11. References</h2>


<div class=bib><div id=bib-item-N1692 class=bib-item>
<a href="https://wg21%2elink/n1692">[N1692]</a>
<span class=bib-author>M.J. Kronenburg.</span>
<span class=bib-title>A Proposal to add the Infinite Precision Integer to the C++ Standard Library</span>
<span class=bib-date>2004-07-01</span>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg21/docs/papers/2004/n1692%2epdf" class=bib-link>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1692.pdf</a></div><div id=bib-item-N1744 class=bib-item>
<a href="https://wg21%2elink/n1744">[N1744]</a>
<span class=bib-author>Michiel Salters.</span>
<span class=bib-title>Big Integer Library Proposal for C++0x</span>
<span class=bib-date>2005-01-13</span>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg21/docs/papers/2005/n1744%2epdf" class=bib-link>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1744.pdf</a></div><div id=bib-item-N4038 class=bib-item>
<a href="https://wg21%2elink/n4038">[N4038]</a>
<span class=bib-author>Pete Becker.</span>
<span class=bib-title>Proposal for Unbounded-Precision Integer Types</span>
<span class=bib-date>2014-05-23</span>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg21/docs/papers/2014/n4038%2ehtml" class=bib-link>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4038.html</a></div><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-P3140R0 class=bib-item>
<a href="https://wg21%2elink/p3140r0">[P3140R0]</a>
<span class=bib-author>Jan Schultke.</span>
<span class=bib-title>std::int_least128_t</span>
<span class=bib-date>2025-02-11</span>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg21/docs/papers/2024/p3140r0%2ehtml" class=bib-link>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3140r0.html</a></div><div id=bib-item-P3161R4 class=bib-item>
<a href="https://wg21%2elink/p3161r4">[P3161R4]</a>
<span class=bib-author>Tiago Freire.</span>
<span class=bib-title>Unified integer overflow arithmetic</span>
<span class=bib-date>2025-03-24</span>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg21/docs/papers/2025/p3161r4%2ehtml" class=bib-link>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3161r4.html</a></div><div id=bib-item-P3639R0 class=bib-item>
<a href="https://wg21%2elink/p3639r0">[P3639R0]</a>
<span class=bib-author>Jan Schultke.</span>
<span class=bib-title>The _BitInt Debate</span>
<span class=bib-date>2025-02-20</span>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg21/docs/papers/2025/p3639r0%2ehtml" class=bib-link>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3639r0.html</a></div><div id=bib-item-P3312R1 class=bib-item>
<a href="https://wg21%2elink/p3312r1">[P3312R1]</a>
<span class=bib-author>Bengt Gustafsson.</span>
<span class=bib-title>Overload Set Types</span>
<span class=bib-date>2025-04-16</span>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg21/docs/papers/2025/p3312r1%2epdf" class=bib-link>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3312r1.pdf</a></div><div id=bib-item-P3438R0 class=bib-item>
<a href="https://wg21%2elink/p3438r0">[P3438R0]</a>
<span class=bib-author>Andreas Fertig.</span>
<span class=bib-title>Make integral overloads of std::to_string constexpr</span>
<span class=bib-date>2024-10-13</span>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg21/docs/papers/2024/p3438r0%2epdf" class=bib-link>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3438r0.pdf</a></div><div id=bib-item-N2763 class=bib-item>
<a href="https://open-std%2eorg/JTC1/SC22/WG14/www/docs/n2763%2epdf">[N2763]</a>
<span class=bib-author>Aaron Ballman, Melanie Blower, Tommy Hoffner, Erich Keane.</span>
<span class=bib-title>Adding a Fundamental Type for N-bit integers</span>
<span class=bib-date>2021-06-21</span>
<a href="https://open-std%2eorg/JTC1/SC22/WG14/www/docs/n2763%2epdf" class=bib-link>https://open-std.org/JTC1/SC22/WG14/www/docs/n2763.pdf</a></div><div id=bib-item-N2775 class=bib-item>
<a href="https://open-std%2eorg/JTC1/SC22/WG14/www/docs/n2775%2epdf">[N2775]</a>
<span class=bib-author>Aaron Ballman, Melanie Blower.</span>
<span class=bib-title>Literal suffixes for bit-precise integers</span>
<span class=bib-date>2021-07-13</span>
<a href="https://open-std%2eorg/JTC1/SC22/WG14/www/docs/n2775%2epdf" class=bib-link>https://open-std.org/JTC1/SC22/WG14/www/docs/n2775.pdf</a></div><div id=bib-item-N3550 class=bib-item>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg14/www/docs/n3550%2epdf">[N3550]</a>
<span class=bib-author>JeanHeyd Meneide.</span>
<span class=bib-title>ISO/IEC 9899:202y (en) — N3550 working draft</span>
<span class=bib-date>2025-05-04</span>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg14/www/docs/n3550%2epdf" class=bib-link>https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3550.pdf</a></div><div id=bib-item-N3644 class=bib-item>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg14/www/docs/n3644%2epdf">[N3644]</a>
<span class=bib-author>Robert C. Seacord.</span>
<span class=bib-title>Integer Sets, v2</span>
<span class=bib-date>2025-07-05</span>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg14/www/docs/n3644%2epdf" class=bib-link>https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3644.pdf</a></div></div>
</main></body>
</html>
