<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2023-09-27" />
  <title>Reconsider Redeclaring static constexpr Data Members</title>
  <style>
      code{white-space: pre-wrap;}
      span.smallcaps{font-variant: small-caps;}
      span.underline{text-decoration: underline;}
      div.column{display: inline-block; vertical-align: top; width: 50%;}
      div.csl-block{margin-left: 1.5em;}
      ul.task-list{list-style: none;}
      pre > code.sourceCode { white-space: pre; position: relative; }
      pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
      pre > code.sourceCode > span:empty { height: 1.2em; }
      .sourceCode { overflow: visible; }
      code.sourceCode > span { color: inherit; text-decoration: inherit; }
      div.sourceCode { margin: 1em 0; }
      pre.sourceCode { margin: 0; }
      @media screen {
      div.sourceCode { overflow: auto; }
      }
      @media print {
      pre > code.sourceCode { white-space: pre-wrap; }
      pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
      }
      pre.numberSource code
        { counter-reset: source-line 0; }
      pre.numberSource code > span
        { position: relative; left: -4em; counter-increment: source-line; }
      pre.numberSource code > span > a:first-child::before
        { content: counter(source-line);
          position: relative; left: -1em; text-align: right; vertical-align: baseline;
          border: none; display: inline-block;
          -webkit-touch-callout: none; -webkit-user-select: none;
          -khtml-user-select: none; -moz-user-select: none;
          -ms-user-select: none; user-select: none;
          padding: 0 4px; width: 4em;
          color: #aaaaaa;
        }
      pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
      div.sourceCode
        {  background-color: #f6f8fa; }
      @media screen {
      pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
      }
      code span { } /* Normal */
      code span.al { color: #ff0000; } /* Alert */
      code span.an { } /* Annotation */
      code span.at { } /* Attribute */
      code span.bn { color: #9f6807; } /* BaseN */
      code span.bu { color: #9f6807; } /* BuiltIn */
      code span.cf { color: #00607c; } /* ControlFlow */
      code span.ch { color: #9f6807; } /* Char */
      code span.cn { } /* Constant */
      code span.co { color: #008000; font-style: italic; } /* Comment */
      code span.cv { color: #008000; font-style: italic; } /* CommentVar */
      code span.do { color: #008000; } /* Documentation */
      code span.dt { color: #00607c; } /* DataType */
      code span.dv { color: #9f6807; } /* DecVal */
      code span.er { color: #ff0000; font-weight: bold; } /* Error */
      code span.ex { } /* Extension */
      code span.fl { color: #9f6807; } /* Float */
      code span.fu { } /* Function */
      code span.im { } /* Import */
      code span.in { color: #008000; } /* Information */
      code span.kw { color: #00607c; } /* Keyword */
      code span.op { color: #af1915; } /* Operator */
      code span.ot { } /* Other */
      code span.pp { color: #6f4e37; } /* Preprocessor */
      code span.re { } /* RegionMarker */
      code span.sc { color: #9f6807; } /* SpecialChar */
      code span.ss { color: #9f6807; } /* SpecialString */
      code span.st { color: #9f6807; } /* String */
      code span.va { } /* Variable */
      code span.vs { color: #9f6807; } /* VerbatimString */
      code span.wa { color: #008000; font-weight: bold; } /* Warning */
      code.diff {color: #898887}
      code.diff span.va {color: #006e28}
      code.diff span.st {color: #bf0303}
  </style>
  <style type="text/css">
body {
margin: 5em;
font-family: serif;

hyphens: auto;
line-height: 1.35;
text-align: justify;
}
@media screen and (max-width: 30em) {
body {
margin: 1.5em;
}
}
div.wrapper {
max-width: 60em;
margin: auto;
}
ul {
list-style-type: none;
padding-left: 2em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
a {
text-decoration: none;
color: #4183C4;
}
a.hidden_link {
text-decoration: none;
color: inherit;
}
li {
margin-top: 0.6em;
margin-bottom: 0.6em;
}
h1, h2, h3, h4 {
position: relative;
line-height: 1;
}
a.self-link {
position: absolute;
top: 0;
left: calc(-1 * (3.5rem - 26px));
width: calc(3.5rem - 26px);
height: 2em;
text-align: center;
border: none;
transition: opacity .2s;
opacity: .5;
font-family: sans-serif;
font-weight: normal;
font-size: 83%;
}
a.self-link:hover { opacity: 1; }
a.self-link::before { content: "§"; }
ul > li:before {
content: "\2014";
position: absolute;
margin-left: -1.5em;
}
:target { background-color: #C9FBC9; }
:target .codeblock { background-color: #C9FBC9; }
:target ul { background-color: #C9FBC9; }
.abbr_ref { float: right; }
.folded_abbr_ref { float: right; }
:target .folded_abbr_ref { display: none; }
:target .unfolded_abbr_ref { float: right; display: inherit; }
.unfolded_abbr_ref { display: none; }
.secnum { display: inline-block; min-width: 35pt; }
.header-section-number { display: inline-block; min-width: 35pt; }
.annexnum { display: block; }
div.sourceLinkParent {
float: right;
}
a.sourceLink {
position: absolute;
opacity: 0;
margin-left: 10pt;
}
a.sourceLink:hover {
opacity: 1;
}
a.itemDeclLink {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
opacity: 0;
}
a.itemDeclLink:hover { opacity: 1; }
span.marginalizedparent {
position: relative;
left: -5em;
}
li span.marginalizedparent { left: -7em; }
li ul > li span.marginalizedparent { left: -9em; }
li ul > li ul > li span.marginalizedparent { left: -11em; }
li ul > li ul > li ul > li span.marginalizedparent { left: -13em; }
div.footnoteNumberParent {
position: relative;
left: -4.7em;
}
a.marginalized {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
}
a.enumerated_item_num {
position: relative;
left: -3.5em;
display: inline-block;
margin-right: -3em;
text-align: right;
width: 3em;
}
div.para { margin-bottom: 0.6em; margin-top: 0.6em; text-align: justify; }
div.section { text-align: justify; }
div.sentence { display: inline; }
span.indexparent {
display: inline;
position: relative;
float: right;
right: -1em;
}
a.index {
position: absolute;
display: none;
}
a.index:before { content: "⟵"; }

a.index:target {
display: inline;
}
.indexitems {
margin-left: 2em;
text-indent: -2em;
}
div.itemdescr {
margin-left: 3em;
}
.bnf {
font-family: serif;
margin-left: 40pt;
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.ncbnf {
font-family: serif;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
}
.ncsimplebnf {
font-family: serif;
font-style: italic;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
background: inherit; 
}
span.textnormal {
font-style: normal;
font-family: serif;
white-space: normal;
display: inline-block;
}
span.rlap {
display: inline-block;
width: 0px;
}
span.descr { font-style: normal; font-family: serif; }
span.grammarterm { font-style: italic; }
span.term { font-style: italic; }
span.terminal { font-family: monospace; font-style: normal; }
span.nonterminal { font-style: italic; }
span.tcode { font-family: monospace; font-style: normal; }
span.textbf { font-weight: bold; }
span.textsc { font-variant: small-caps; }
a.nontermdef { font-style: italic; font-family: serif; }
span.emph { font-style: italic; }
span.techterm { font-style: italic; }
span.mathit { font-style: italic; }
span.mathsf { font-family: sans-serif; }
span.mathrm { font-family: serif; font-style: normal; }
span.textrm { font-family: serif; }
span.textsl { font-style: italic; }
span.mathtt { font-family: monospace; font-style: normal; }
span.mbox { font-family: serif; font-style: normal; }
span.ungap { display: inline-block; width: 2pt; }
span.textit { font-style: italic; }
span.texttt { font-family: monospace; }
span.tcode_in_codeblock { font-family: monospace; font-style: normal; }
span.phantom { color: white; }

span.math { font-style: normal; }
span.mathblock {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 1.2em;
margin-bottom: 1.2em;
text-align: center;
}
span.mathalpha {
font-style: italic;
}
span.synopsis {
font-weight: bold;
margin-top: 0.5em;
display: block;
}
span.definition {
font-weight: bold;
display: block;
}
.codeblock {
margin-left: 1.2em;
line-height: 127%;
}
.outputblock {
margin-left: 1.2em;
line-height: 127%;
}
div.itemdecl {
margin-top: 2ex;
}
code.itemdeclcode {
white-space: pre;
display: block;
}
span.textsuperscript {
vertical-align: super;
font-size: smaller;
line-height: 0;
}
.footnotenum { vertical-align: super; font-size: smaller; line-height: 0; }
.footnote {
font-size: small;
margin-left: 2em;
margin-right: 2em;
margin-top: 0.6em;
margin-bottom: 0.6em;
}
div.minipage {
display: inline-block;
margin-right: 3em;
}
div.numberedTable {
text-align: center;
margin: 2em;
}
div.figure {
text-align: center;
margin: 2em;
}
table {
border: 1px solid black;
border-collapse: collapse;
margin-left: auto;
margin-right: auto;
margin-top: 0.8em;
text-align: left;
hyphens: none; 
}
td, th {
padding-left: 1em;
padding-right: 1em;
vertical-align: top;
}
td.empty {
padding: 0px;
padding-left: 1px;
}
td.left {
text-align: left;
}
td.right {
text-align: right;
}
td.center {
text-align: center;
}
td.justify {
text-align: justify;
}
td.border {
border-left: 1px solid black;
}
tr.rowsep, td.cline {
border-top: 1px solid black;
}
tr.even, tr.odd {
border-bottom: 1px solid black;
}
tr.capsep {
border-top: 3px solid black;
border-top-style: double;
}
tr.header {
border-bottom: 3px solid black;
border-bottom-style: double;
}
th {
border-bottom: 1px solid black;
}
span.centry {
font-weight: bold;
}
div.table {
display: block;
margin-left: auto;
margin-right: auto;
text-align: center;
width: 90%;
}
span.indented {
display: block;
margin-left: 2em;
margin-bottom: 1em;
margin-top: 1em;
}
ol.enumeratea { list-style-type: none; background: inherit; }
ol.enumerate { list-style-type: none; background: inherit; }

code.sourceCode > span { display: inline; }
</style>
  <link href="data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center">Reconsider Redeclaring
static constexpr Data Members</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2984R0</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2023-09-27</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      Library Evolution<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Alisdair Meredith<br>&lt;<a href="mailto:ameredith1@bloomberg.net" class="email">ameredith1@bloomberg.net</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#abstract" id="toc-abstract"><span class="toc-section-number">1</span> Abstract<span></span></a></li>
<li><a href="#rev.hist" id="toc-rev.hist"><span class="toc-section-number">2</span> Revision history<span></span></a>
<ul>
<li><a href="#r0-october-2023-pre-kona-mailing" id="toc-r0-october-2023-pre-kona-mailing">R0 October 2023 (pre-Kona
mailing)<span></span></a></li>
</ul></li>
<li><a href="#intro" id="toc-intro"><span class="toc-section-number">3</span> Introduction<span></span></a></li>
<li><a href="#history" id="toc-history"><span class="toc-section-number">4</span> History<span></span></a>
<ul>
<li><a href="#history.constexpr" id="toc-history.constexpr"><span class="toc-section-number">4.1</span> Introducing
<code class="sourceCode default">constexpr</code> in
C++11<span></span></a></li>
<li><a href="#history.inline" id="toc-history.inline"><span class="toc-section-number">4.2</span> Introducing inline variables in
C++17<span></span></a></li>
<li><a href="#history.varna" id="toc-history.varna"><span class="toc-section-number">4.3</span> 2023 Varna meeting: initial EWG
review<span></span></a></li>
</ul></li>
<li><a href="#analysis" id="toc-analysis"><span class="toc-section-number">5</span> Analysis<span></span></a>
<ul>
<li><a href="#asys.standard" id="toc-asys.standard"><span class="toc-section-number">5.1</span> What the C++ Standard
says<span></span></a></li>
<li><a href="#asys.workaround" id="toc-asys.workaround"><span class="toc-section-number">5.2</span> Workarounds<span></span></a></li>
<li><a href="#asys.warning" id="toc-asys.warning"><span class="toc-section-number">5.3</span> Current
practice<span></span></a></li>
</ul></li>
<li><a href="#proposal" id="toc-proposal"><span class="toc-section-number">6</span> Proposal<span></span></a>
<ul>
<li><a href="#prop.statusquo" id="toc-prop.statusquo"><span class="toc-section-number">6.1</span> Status quo<span></span></a></li>
<li><a href="#prop.undeprecate" id="toc-prop.undeprecate"><span class="toc-section-number">6.2</span> Undeprecate the redundant
redeclarations for C++26<span></span></a></li>
<li><a href="#prop.remove" id="toc-prop.remove"><span class="toc-section-number">6.3</span> Remove the deprecated redundant
redeclaration from C++26<span></span></a></li>
</ul></li>
<li><a href="#ack" id="toc-ack"><span class="toc-section-number">7</span>
Acknowledgements<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">8</span> References<span></span></a></li>
</ul>
</div>
<!-- RENDER AS html TO SUPPORT USE OF <blockquote> MARKUP -->
<h1 data-number="1" id="abstract"><span class="header-section-number">1</span> Abstract<a href="#abstract" class="self-link"></a></h1>
<p>With the introduction of inline variables in C++17,
<code class="sourceCode default">static constexpr</code> data members
are defined by their in-class declarations and the legacy out-of-class
definitions became redundant redeclarations and were deprecated. This
paper examines the feasibility of removing support for the deprecated
redeclarations, and whether undeprecation would be the better
forward-looking policy.</p>
<h1 data-number="2" id="rev.hist"><span class="header-section-number">2</span> Revision history<a href="#rev.hist" class="self-link"></a></h1>
<h2 class="unnumbered" id="r0-october-2023-pre-kona-mailing">R0 October
2023 (pre-Kona mailing)<a href="#r0-october-2023-pre-kona-mailing" class="self-link"></a></h2>
<ul>
<li>Initial draft of this paper</li>
</ul>
<h1 data-number="3" id="intro"><span class="header-section-number">3</span> Introduction<a href="#intro" class="self-link"></a></h1>
<p>At the start of the C++23 cycle, <span class="citation" data-cites="P2139R2">[<a href="#ref-P2139R2" role="doc-biblioref">P2139R2</a>]</span> tried to review each deprecated
feature of C++, to see which we would benefit from actively removing,
and which might now be better undeprecated. Consolidating all this
analysis into one place was intended to ease the (L)EWG review process,
but in return gave the author so much feedback that the next revision of
that paper was not completed.</p>
<p>For the C++26 cycle there will be a concise paper tracking the
overall review process, <span class="citation" data-cites="P2863R2">[<a href="#ref-P2863R2" role="doc-biblioref">P2863R2</a>]</span>, but all
changes to the standard will be pursued through specific papers,
decoupling progress from the larger paper so that delays on a single
feature do not hold up progress on all.</p>
<p>This paper takes up the deprecated redeclaration of
<code class="sourceCode default">constexpr</code> data members,
<span>D.6
<a href="https://wg21.link/depr.static.constexpr">[depr.static.constexpr]</a></span>.</p>
<h1 data-number="4" id="history"><span class="header-section-number">4</span> History<a href="#history" class="self-link"></a></h1>
<h2 data-number="4.1" id="history.constexpr"><span class="header-section-number">4.1</span> Introducing
<code class="sourceCode default">constexpr</code> in C++11<a href="#history.constexpr" class="self-link"></a></h2>
<p>The first C++ Standard to support
<code class="sourceCode default">static constexpr</code> data members
was C++11, with the introduction of the
<code class="sourceCode default">constexpr</code> keyword.</p>
<h2 data-number="4.2" id="history.inline"><span class="header-section-number">4.2</span> Introducing inline variables in
C++17<a href="#history.inline" class="self-link"></a></h2>
<p>Definitions for
<code class="sourceCode default">static constexpr</code> data members
outside the enclosing class definition became redundant redeclarations
with the application of <span class="citation" data-cites="P0386R2">[<a href="#ref-P0386R2" role="doc-biblioref">P0386R2</a>]</span> for C++17,
inline variables. Such redeclarations were consequently deprecated,
although considered harmless. There has been no further progress on this
topic in the last seven years.</p>
<h2 data-number="4.3" id="history.varna"><span class="header-section-number">4.3</span> 2023 Varna meeting: initial EWG
review<a href="#history.varna" class="self-link"></a></h2>
<p>At the Varna meeting in 2023, the deprecation of <span>D.6
<a href="https://wg21.link/depr.static.constexpr">[depr.static.constexpr]</a></span>
was presented in the context of maintaining status quo, as presented in
paper P2863R0.</p>
<p>While there was unanimous agreement that removal from C++26 seemed a
bad idea, there was interest in soliciting a paper to propose
undeprecation.</p>
<p>Poll: EWG is interested in un-deprecating defining
<code class="sourceCode default">inline constexpr</code> class variables
(P2863R0 section 6.6).</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>SF   F   N   A  SA</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> 2  12   7   3   0</span></code></pre></div>
<p>Result: Consensus to request a paper, which you are now reading.</p>
<h1 data-number="5" id="analysis"><span class="header-section-number">5</span> Analysis<a href="#analysis" class="self-link"></a></h1>
<h2 data-number="5.1" id="asys.standard"><span class="header-section-number">5.1</span> What the C++ Standard says<a href="#asys.standard" class="self-link"></a></h2>
<p>According to <span>9.2.6
<a href="https://wg21.link/dcl.constexpr">[dcl.constexpr]</a></span>,
<code class="sourceCode default">static constexpr</code> data members of
a class are implicitly defined as inline variables:</p>
<blockquote>
<span class="marginalizedparent"><a class="marginalized">3</a></span> A
function or static data member declared with the
<code class="sourceCode default">constexpr</code> or
<code class="sourceCode default">consteval</code> specifier is
implicitly an inline function or variable.
</blockquote>
<p>According to <span>6.2
<a href="https://wg21.link/basic.def">[basic.def]</a></span>, inline
static data member declarations are also definitions (by inference of
not being excluded), and the following bullets clarify that further
declarations outside the class are just that, declarations and not
definitions.</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
Each entity declared by a declaration is also defined by that
declaration unless:</p>
<p><span class="marginalizedparent"><a class="marginalized">(2.3)</a></span> — it
declares a non-inline static data member in a class definition
(<span>11.4
<a href="https://wg21.link/class.mem">[class.mem]</a></span>,
<span>11.4.9
<a href="https://wg21.link/class.static">[class.static]</a></span>),</p>
<span class="marginalizedparent"><a class="marginalized">(2.4)</a></span> — it
declares a static data member outside a class definition and the
variable was defined within the class with the constexpr specifier
(<span>11.4.9.3
<a href="https://wg21.link/class.static.data">[class.static.data]</a></span>)
(this usage is deprecated; see <span>D.6
<a href="https://wg21.link/depr.static.constexpr">[depr.static.constexpr]</a></span>),
</blockquote>
<!--
 meaning another definition outside the class is not necessary, and
would count as multiple definitions if the subsequent definitions were not also
deemed inline.  However such definitions outside the class were essential from
C++11 until C++17 as the declaration in the enclosing class definition was
just that, a declaration and not a definition.
  -->
<h2 data-number="5.2" id="asys.workaround"><span class="header-section-number">5.2</span> Workarounds<a href="#asys.workaround" class="self-link"></a></h2>
<p>When considering the removal of redundant definitions, it seems
simple enough to support a code base that is common with C++11 and the
feature removal (or warned deprecation) with a simple feature check:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>C++11 and C++14</strong>
</div></th>
<th><div style="text-align:center">
<strong>Portable with no deprecation</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> Type <span class="op">=</span> <span class="dt">int</span>;</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Class <span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>   Type Member <span class="op">=</span> <span class="op">{}</span>;</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> Type Class<span class="op">::</span>Member;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> Type <span class="op">=</span> <span class="dt">int</span>;</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Class <span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>   Type Member <span class="op">=</span> <span class="op">{}</span>;</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>#if</ins></span> <span class="add" style="color: #006e28"><ins>!defined(__cpp_inline_variables)</ins></span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> Type Class<span class="op">::</span>Member;</span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>#endif</ins></span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>Note that the Portable code works both before and after C++17, and
whether or not the redundant redeclaration is deprecated (removing a
warning) or ill-formed if support for redeclarations were removed from a
future standard. Once a codebase establishes that its minimum supported
dialect of C++ is C++17 or later the conditionally translated code can
be removed completely.</p>
<h2 data-number="5.3" id="asys.warning"><span class="header-section-number">5.3</span> Current practice<a href="#asys.warning" class="self-link"></a></h2>
<p>As of writing this paper in September 2023, none of the 4 major
compiler front ends report a deprecated-use warning on the example in
the standard, including the latest trunk build for open source
compilers.</p>
<p>Example code from <span>D.6
<a href="https://wg21.link/depr.static.constexpr">[depr.static.constexpr]</a></span>:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> A <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>   <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">int</span> n <span class="op">=</span> <span class="dv">5</span>;  <span class="co">// definition (declaration in C++ 2014)</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">int</span> A<span class="op">::</span>n;             <span class="co">// redundant declaration (definition in C++ 2014)</span></span></code></pre></div>
<p>All the latest compiler available through Godbolt compiler explorer
were tested with <code class="sourceCode default">-Wall -Wextra</code>
except MSVC which was tested with
<code class="sourceCode default">\W4</code>. Language dialect tested was
C++20, as that is a common base for all compilers, and this feature has
been deprecated since the earlier C++17.</p>
<table>
<thead>
<tr class="header">
<th style="text-align: left;"><div style="text-align:center">
<strong>Compiler</strong>
</div></th>
<th style="text-align: left;"><div style="text-align:center">
<strong>Warn since</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">Clang</td>
<td style="text-align: left;">no warnings</td>
</tr>
<tr class="even">
<td style="text-align: left;">GCC</td>
<td style="text-align: left;">no warnings</td>
</tr>
<tr class="odd">
<td style="text-align: left;">MSVC</td>
<td style="text-align: left;">no warnings</td>
</tr>
<tr class="even">
<td style="text-align: left;">nvc++/EDG</td>
<td style="text-align: left;">no warnings</td>
</tr>
</tbody>
</table>
<h1 data-number="6" id="proposal"><span class="header-section-number">6</span> Proposal<a href="#proposal" class="self-link"></a></h1>
<p>We might consider several directions to make progress for C++26.</p>
<h2 data-number="6.1" id="prop.statusquo"><span class="header-section-number">6.1</span> Status quo<a href="#prop.statusquo" class="self-link"></a></h2>
<p>Status quo prevails if we do not make a persuasive enough argument to
make a change. However, in this case there is an argument to be made
explicitly in favor of the status quo.</p>
<p>To maintain maintain a simpler language in the long term, it would be
nice to remove a corner case that permits redundant redeclarations where
redeclarations are normally ill-formed. Removing corner cases that serve
no benefit to the modern language avoids the accumulation of “cruft”
that degrades the user experience in long-term ongoing project.</p>
<p>The workaround to make code portable across all C++ dialects is
simple and amenable to tooling that can parse C++, such as through a
fix-it hint from a compiler front end. If we retain the ambition to one
day remove this deprecated feature, we should encourage compiler vendors
to start diagnosing code that relies on it today. Such diagnostics have
been relevant since 2017, and should be deployed without waiting for the
release of the C++26 Standard.</p>
<p>If nothing else, retaining the deprecated status indicates that the
feature is historical baggage and not an essential part of the
language.</p>
<h2 data-number="6.2" id="prop.undeprecate"><span class="header-section-number">6.2</span> Undeprecate the redundant
redeclarations for C++26<a href="#prop.undeprecate" class="self-link"></a></h2>
<p>If we believe that this deprecated feature can never be removed, then
it would be an active disservice to our users for compilers and other
tools to start warning on deprecated usage. In such case, we should
actively consider undeprecating redundant redeclaration of
<code class="sourceCode default">static constexpr</code> data
members.</p>
<h3 data-number="6.2.1" id="wording.undeprecate"><span class="header-section-number">6.2.1</span> Proposed wording<a href="#wording.undeprecate" class="self-link"></a></h3>
<p>Make the following changes to the C++ Working Draft, undeprecating
redundant redeclaration of
<code class="sourceCode default">constexpr</code> data members outside
their class. All wording is relative to <span class="citation" data-cites="N4958">[<a href="#ref-N4958" role="doc-biblioref">N4958</a>]</span>, the latest draft at the time of
writing.</p>
<h4 data-number="6.2.1.1" id="remove-deprecation-notices-from-the-core-clauses"><span class="header-section-number">6.2.1.1</span> Remove deprecation notices
from the core clauses<a href="#remove-deprecation-notices-from-the-core-clauses" class="self-link"></a></h4>
<h3 class="unnumbered" id="basic.def-declarations-and-definitions"><span>6.2
<a href="https://wg21.link/basic.def">[basic.def]</a></span>
Declarations and definitions<a href="#basic.def-declarations-and-definitions" class="self-link"></a></h3>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
Each entity declared by a declaration is also defined by that
declaration unless:</p>
<p><span class="marginalizedparent"><a class="marginalized">(2.4)</a></span> — it
declares a static data member outside a class definition and the
variable was defined within the class with the
<code class="sourceCode default">constexpr</code> specifier
(<span>11.4.9.3
<a href="https://wg21.link/class.static.data">[class.static.data]</a></span>)
<span class="rm" style="color: #bf0303"><del>(this usage is deprecated;
see <span>D.6
<a href="https://wg21.link/depr.static.constexpr">[depr.static.constexpr]</a></span>)</del></span>,</p>
<h3 class="unnumbered" id="class.static.data-static-data-members"><span>11.4.9.3
<a href="https://wg21.link/class.static.data">[class.static.data]</a></span>
Static data members<a href="#class.static.data-static-data-members" class="self-link"></a></h3>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
If a non-volatile non-inline
<code class="sourceCode default">const</code> static data member is of
integral or enumeration type, its declaration in the class definition
can specify a <em>brace-or-equal-initializer</em> in which every
<em>initializer-clause</em> that is an <em>assignment-expression</em> is
a constant expression (<span>7.7
<a href="https://wg21.link/expr.const">[expr.const]</a></span>). The
member shall still be defined in a namespace scope if it is odr-used
(<span>6.3
<a href="https://wg21.link/basic.def.odr">[basic.def.odr]</a></span>) in
the program and the namespace scope definition shall not contain an
<em>initializer</em>. The declaration of an inline static data member
(which is a definition) may specify a
<em>brace-or-equal-initializer</em>. If the member is declared with the
<code class="sourceCode default">constexpr</code> specifier, it may be
redeclared in namespace scope with no initializer <span class="rm" style="color: #bf0303"><del>(this usage is deprecated; see <span>D.6
<a href="https://wg21.link/depr.static.constexpr">[depr.static.constexpr]</a></span>)</del></span>.
Declarations of other static data members shall not specify a
<em>brace-or-equal-initializer</em>.</p>
<h4 data-number="6.2.1.2" id="review-annex-c"><span class="header-section-number">6.2.1.2</span> Review Annex C<a href="#review-annex-c" class="self-link"></a></h4>
<p>No changes are needed for Annex C, as restoring deprecated
functionality does not risk any breakage.</p>
<h4 data-number="6.2.1.3" id="strike-wording-from-annex-d"><span class="header-section-number">6.2.1.3</span> Strike wording from Annex
D<a href="#strike-wording-from-annex-d" class="self-link"></a></h4>
<div class="rm" style="color: #bf0303">

<h3 class="unnumbered" id="depr.static.constexpr-redeclaration-of-static-constexpr-data-members"><span>D.6
<a href="https://wg21.link/depr.static.constexpr">[depr.static.constexpr]</a></span>
Redeclaration of
<code class="sourceCode default">static constexpr</code> data members<a href="#depr.static.constexpr-redeclaration-of-static-constexpr-data-members" class="self-link"></a></h3>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
For compatibility with prior revisions of C++, a
<code class="sourceCode default">constexpr static</code> data member may
be redundantly redeclared outside the class with no initializer
(<span>6.2
<a href="https://wg21.link/basic.def">[basic.def]</a></span>,
<span>11.4.9.3
<a href="https://wg21.link/class.static.data">[class.static.data]</a></span>).
This usage is deprecated.</p>
<p>[<em>Example 1:</em></p>
<div class="sourceCode" id="cb5"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>  struct A {</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    static constexpr int n = 5;   // definition (declaration in C++ 2014)</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  };</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>  constexpr int A::n;             // redundant declaration (definition in C++ 2014)</span></code></pre></div>
<p>—<em>end example</em>]</p>
</div>
<h4 data-number="6.2.1.4" id="update-cross-reference-for-stable-labels-for-c23"><span class="header-section-number">6.2.1.4</span> Update cross-reference for
stable labels for C++23<a href="#update-cross-reference-for-stable-labels-for-c23" class="self-link"></a></h4>
<h3 class="unnumbered" id="cross-references-from-iso-c-2023">Cross-references from ISO C++
2023<a href="#cross-references-from-iso-c-2023" class="self-link"></a></h3>
<p>All clause and subclause labels from ISO C++ 2023 (ISO/IEC
14882:2023, <em>Programming Languages — C++</em>) are present in this
document, with the exceptions described below.</p>
<p>container.gen.reqmts <em>see</em><br />
    container.requirements.general</p>
<p>depr.res.on.required <em>removed</em><br />
<span class="add" style="color: #006e28"><ins>depr.static.constexpr
<em>removed</em></ins></span><br />
</p>
<h2 data-number="6.3" id="prop.remove"><span class="header-section-number">6.3</span> Remove the deprecated redundant
redeclaration from C++26<a href="#prop.remove" class="self-link"></a></h2>
<p>Given the lack of deprecation warnings issued at the time of writing,
6 years after the redundant redeclarations were formally deprecated in a
published standard, it seems unreasonable to recommend removal at this
time. Since the deprecated syntax was actually required by C++11 and
C++14 (prior to C++11 there was no
<code class="sourceCode default">constexpr</code> keyword) it is likely
that a lot of current code would break upon removing this feature
without a transitional period where compilers do issue warnings about
the current deprecation.</p>
<p>That said, the workaround to make code portable across all C++
dialects is simple and amenable to tooling that can parse C++, such as
through a fix-it hint from a compiler front end.</p>
<h3 data-number="6.3.1" id="wording.remove"><span class="header-section-number">6.3.1</span> Proposed wording<a href="#wording.remove" class="self-link"></a></h3>
<p>Make the following changes to the C++ Working Draft, making redundant
redeclaration of <code class="sourceCode default">constexpr</code> data
members outside their class ill-formed. All wording is relative to <span class="citation" data-cites="N4958">[<a href="#ref-N4958" role="doc-biblioref">N4958</a>]</span>, the latest draft at the time of
writing.</p>
<h3 class="unnumbered" id="basic.def-declarations-and-definitions-1"><span>6.2
<a href="https://wg21.link/basic.def">[basic.def]</a></span>
Declarations and definitions<a href="#basic.def-declarations-and-definitions-1" class="self-link"></a></h3>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
Each entity declared by a declaration is also defined by that
declaration unless:</p>
<p><span class="marginalizedparent"><a class="marginalized">(2.4)</a></span>
<span class="rm" style="color: #bf0303"><del>— it declares a static data
member outside a class definition and the variable was defined within
the class with the
<span><code class="sourceCode default">constexpr</code></span> specifier
(<span>11.4.9.3
<a href="https://wg21.link/class.static.data">[class.static.data]</a></span>)
(this usage is deprecated; see <span>D.6
<a href="https://wg21.link/depr.static.constexpr">[depr.static.constexpr]</a></span>)</del></span>,</p>
<h3 class="unnumbered" id="class.static.data-static-data-members-1"><span>11.4.9.3
<a href="https://wg21.link/class.static.data">[class.static.data]</a></span>
Static data members<a href="#class.static.data-static-data-members-1" class="self-link"></a></h3>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
If a non-volatile non-inline
<code class="sourceCode default">const</code> static data member is of
integral or enumeration type, its declaration in the class definition
can specify a <em>brace-or-equal-initializer</em> in which every
<em>initializer-clause</em> that is an <em>assignment-expression</em> is
a constant expression (<span>7.7
<a href="https://wg21.link/expr.const">[expr.const]</a></span>). The
member shall still be defined in a namespace scope if it is odr-used
(<span>6.3
<a href="https://wg21.link/basic.def.odr">[basic.def.odr]</a></span>) in
the program and the namespace scope definition shall not contain an
<em>initializer</em>. The declaration of an inline static data member
(which is a definition) may specify a
<em>brace-or-equal-initializer</em>. <span class="rm" style="color: #bf0303"><del>If the member is declared with the
<span><code class="sourceCode default">constexpr</code></span>
specifier, it may be redeclared in namespace scope with no initializer
(this usage is deprecated; see <span>D.6
<a href="https://wg21.link/depr.static.constexpr">[depr.static.constexpr]</a></span>)</del></span>.
Declarations of other static data members shall not specify a
<em>brace-or-equal-initializer</em>.</p>
<h4 data-number="6.3.1.1" id="update-annex-c"><span class="header-section-number">6.3.1.1</span> Update Annex C<a href="#update-annex-c" class="self-link"></a></h4>
<p>TBD</p>
<div class="add" style="color: #006e28">
<p>[<em>Example 1:</em></p>
<div class="sourceCode" id="cb6"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>  struct A {</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    static constexpr int n = 5;   // inline variable definition</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  };</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>  constexpr int A::n;             // ill-formed redeclaration in C++ 2026</span></code></pre></div>
<p>—<em>end example</em>]</p>
</div>
<h4 data-number="6.3.1.2" id="strike-wording-from-annex-d-1"><span class="header-section-number">6.3.1.2</span> Strike wording from Annex
D<a href="#strike-wording-from-annex-d-1" class="self-link"></a></h4>
<div class="rm" style="color: #bf0303">

<h3 class="unnumbered" id="depr.static.constexpr-redeclaration-of-static-constexpr-data-members-1"><span>D.6
<a href="https://wg21.link/depr.static.constexpr">[depr.static.constexpr]</a></span>
Redeclaration of
<code class="sourceCode default">static constexpr</code> data members<a href="#depr.static.constexpr-redeclaration-of-static-constexpr-data-members-1" class="self-link"></a></h3>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
For compatibility with prior revisions of C++, a
<code class="sourceCode default">constexpr static</code> data member may
be redundantly redeclared outside the class with no initializer
(<span>6.2
<a href="https://wg21.link/basic.def">[basic.def]</a></span>,
<span>11.4.9.3
<a href="https://wg21.link/class.static.data">[class.static.data]</a></span>).
This usage is deprecated.</p>
<p>[<em>Example 1:</em></p>
<div class="sourceCode" id="cb7"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>  struct A {</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>    static constexpr int n = 5;   // definition (declaration in C++ 2014)</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  };</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>  constexpr int A::n;             // redundant declaration (definition in C++ 2014)</span></code></pre></div>
<p>—<em>end example</em>]</p>
</div>
<h4 data-number="6.3.1.3" id="update-cross-reference-for-stable-labels-for-c23-1"><span class="header-section-number">6.3.1.3</span> Update cross-reference for
stable labels for C++23<a href="#update-cross-reference-for-stable-labels-for-c23-1" class="self-link"></a></h4>
<h3 class="unnumbered" id="cross-references-from-iso-c-2023-1">Cross-references from ISO C++
2023<a href="#cross-references-from-iso-c-2023-1" class="self-link"></a></h3>
<p>All clause and subclause labels from ISO C++ 2023 (ISO/IEC
14882:2023, <em>Programming Languages — C++</em>) are present in this
document, with the exceptions described below.</p>
<p>container.gen.reqmts <em>see</em><br />
    container.requirements.general</p>
<p>depr.res.on.required <em>removed</em><br />
<span class="add" style="color: #006e28"><ins>depr.static.constexpr
<em>removed</em></ins></span><br />
</p>
<h1 data-number="7" id="ack"><span class="header-section-number">7</span> Acknowledgements<a href="#ack" class="self-link"></a></h1>
<p>Thanks to Michael Park for the pandoc-based framework used to
transform this document’s source from Markdown.</p>
<!--
# Priorities

There are a number of factors we should consider and weigh when determining
the optimal outcome in review.

## How helpful is the change?

Minimal impact on compilers and tools that must support older dialects

One fewer concern case to confuse students

Minor distractions must be actively removed if we wish to avoid accumulating
a long term technical debt

Shrinking Annex D is its own good thing

## How disruptive is the change?

### How much code will break?

Do we even know how much code will break?

### How much code can we tolerate breaking?

### How easy is it to fix broken code?

### How hard is it to automate code migration?


# Take 2

Never break — don’t disrupt users
Break only after warning
Break only if there is an easy upgrade path
Break only if we have an easy pattern for portable code across standards
Remove corner cases before too many accumulate


Status Quo (stay deprecated)
Remove now
Undeprecate


Concern: never break means never remove


# Take 3

First gate: would we take the feature if we could guarantee no code break

Note: this compatibility feature is the stepping stone to avoid code break in a
      previous change

Sell feature:  It reduces technical debt, but is not in itself a danger

Can we remove it without breaking code?  No, compilers still do not warn

How easy is workaround?  #if to exclude code that depends on feature macro (rather than language version)

Recommend status quo, but ask vendors to start warning
-->
<h1 data-number="8" id="bibliography"><span class="header-section-number">8</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" role="doc-bibliography">
<div id="ref-N4958" class="csl-entry" role="doc-biblioentry">
[N4958] Thomas Köppe. 2023-08-14. Working Draft, Programming Languages —
C++. <a href="https://wg21.link/n4958"><div class="csl-block">https://wg21.link/n4958</div></a>
</div>
<div id="ref-P0386R2" class="csl-entry" role="doc-biblioentry">
[P0386R2] Hal Finkel, Richard Smith. 2016-06-24. Inline Variables. <a href="https://wg21.link/p0386r2"><div class="csl-block">https://wg21.link/p0386r2</div></a>
</div>
<div id="ref-P2139R2" class="csl-entry" role="doc-biblioentry">
[P2139R2] Alisdair Meredith. 2020-07-15. Reviewing Deprecated Facilities
of C++20 for C++23. <a href="https://wg21.link/p2139r2"><div class="csl-block">https://wg21.link/p2139r2</div></a>
</div>
<div id="ref-P2863R2" class="csl-entry" role="doc-biblioentry">
[P2863R2] Alisdair Meredith. 2023-10-15. Review Annex D for C++26. <a href="https://wg21.link/d2863r2"><div class="csl-block">https://wg21.link/d2863r2</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
