<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<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="2025-01-09" />
  <title>Modeling Access Control With Reflection</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>
  <style type="text/css">a {
color : #4183C4;
text-decoration: underline;
}
a.marginalized {
text-decoration: none;
}
a.self-link {
text-decoration: none;
}
h1#toctitle {
border-bottom: 1px solid #cccccc;
}
#TOC li {
margin-top: 1px;
margin-bottom: 1px;
}
#TOC ul>li:before { display: none; }
h3.subtitle { margin-top: -15px; }
h1:target { background-color: transparent; }
h2:target { background-color: transparent; }
h3:target { background-color: transparent; }
h4:target { background-color: transparent; }
h5:target { background-color: transparent; }
h6:target { background-color: transparent; }
code span.co { font-family: monospace; }
table tr {
background-color: white;
}
table tr:nth-child(2n) {
background-color: #f6f8fa;
}
#title-block-header > table tr:nth-child(2n) {
background-color: white;
}
td > div.sourceCode {
background-color: inherit;
}
td > div > div.sourceCode {
background-color: inherit;
}
table {
border-collapse: collapse;
}
table td, table th {
border: 1px solid #cccccc;
}
table th {
border-bottom: 1px solid black;
text-align: center;
}
table tr:first-child th {
border-top: 0;
}
table tr:last-child td {
border-bottom: 0;
}
table tr td:first-child,
table tr th:first-child {
border-left: 0;
}
table tr td:last-child,
table tr th:last-child {
border-right: 0;
}
table tbody tr:first-child td {
border-top: 1px solid black;
}
#title-block-header td { border: 0; }
@media all {
body {
margin: 2em;
}
}
@media screen and (min-width: 480px) {
body {
margin: 5em;
}
}
#refs code{padding-left: 0px; text-indent: 0px;}
:root {
--diff-ins: #C9FBC9;
--diff-strongins: #acf2bd;
--diff-del: #FFC8EB;
--diff-strongdel: #ff8888;
}
span.diffins {
background-color: var(--diff-strongins);
}
span.diffdel {
background-color: var(--diff-strongdel);
}
div.rm { text-decoration: line-through; }
div.rm code.sourceCode { text-decoration: line-through; }
div.addu, span.addu {
color: #006e28;
background-color: var(--diff-ins);
}

div.rm pre, div.add pre { background-color: #f6f8fa; }
div.addu pre { background-color: var(--diff-ins); }
div.add, div.add pre { background-color: var(--diff-ins); }
div.addu blockquote {
border-left: 4px solid #00a000;
padding: 0 15px;
color: #006e28;
text-decoration: none;
}
div.addu blockquote code.sourceCode { text-decoration: none; }
div.addu blockquote pre { text-decoration: none; }
div.addu blockquote pre code { text-decoration: none; }
div.quote {
border-left: 7px solid #ccc;
background: #f9f9f9;
margin: 1.5em 10px;
padding-left: 20px;
}
code.diff span.va { color: #000000; background-color: var(--diff-ins); }
code.diff span.st { color: #000000; background-color: var(--diff-del); }
div.std blockquote { color: #000000; background-color: #F1F1F1;
border: 1px solid #D1D1D1;
padding-left: 0.5em; padding-right: 0.5em; }
div.std.ins blockquote {
color: #000000; background-color: #C8FFC8;
border: 1px solid #B3EBB3;
}
div.ins > div.example {
color: #000000; background-color: #C8FFC8;
border: 1px solid #B3EBB3;
}
div.std div.sourceCode { background-color: inherit; margin-left: 1em; }
div.std blockquote del { text-decoration: line-through;
color: #000000; background-color: var(--diff-del);
border: none; }
code del { border: 1px solid #ECB3C7; }
span.orange {
background-color: #ffa500;
}
span.yellow {
background-color: #ffff00;
}</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">Modeling Access Control With
Reflection</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3547R0 <a href="https://wg21.link/P3547">[Latest]</a> <a href="https://wg21.link/P3547/status">[Status]</a></td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2025-01-09</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>
      SG7, LEWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Dan Katz<br>&lt;<a href="mailto:dkatz85@bloomberg.net" class="email">dkatz85@bloomberg.net</a>&gt;<br>
      Ville Voutilainen<br>&lt;<a href="mailto:ville.voutilainen@gmail.com" class="email">ville.voutilainen@gmail.com</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#abstract" id="toc-abstract"><span class="toc-section-number">1</span> Abstract<span></span></a></li>
<li><a href="#background" id="toc-background"><span class="toc-section-number">2</span> Background<span></span></a>
<ul>
<li><a href="#a-diversity-of-perspectives" id="toc-a-diversity-of-perspectives"><span class="toc-section-number">2.1</span> A diversity of
perspectives<span></span></a></li>
<li><a href="#a-problem-of-composition" id="toc-a-problem-of-composition"><span class="toc-section-number">2.2</span> A problem of
composition<span></span></a></li>
</ul></li>
<li><a href="#proposed-features" id="toc-proposed-features"><span class="toc-section-number">3</span> Proposed features<span></span></a>
<ul>
<li><a href="#explicit-contexts" id="toc-explicit-contexts"><span class="toc-section-number">3.1</span> Explicit
contexts<span></span></a></li>
<li><a href="#integrating-access-control-with-members_of" id="toc-integrating-access-control-with-members_of"><span class="toc-section-number">3.2</span> Integrating access control with
<code class="sourceCode cpp">members_of</code><span></span></a></li>
<li><a href="#modeling-protected-access" id="toc-modeling-protected-access"><span class="toc-section-number">3.3</span> Modeling protected
access<span></span></a></li>
<li><a href="#additional-facilities" id="toc-additional-facilities"><span class="toc-section-number">3.4</span> Additional
facilities<span></span></a></li>
<li><a href="#a-stronger-notion-of-access-control-for-reflection" id="toc-a-stronger-notion-of-access-control-for-reflection"><span class="toc-section-number">3.5</span> A stronger notion of access
control for reflection<span></span></a></li>
<li><a href="#implementation-experience" id="toc-implementation-experience"><span class="toc-section-number">3.6</span> Implementation
experience<span></span></a></li>
</ul></li>
<li><a href="#proposed-wording" id="toc-proposed-wording"><span class="toc-section-number">4</span> Proposed wording<span></span></a>
<ul>
<li><a href="#meta.reflection.synop-header-meta-synopsis" id="toc-meta.reflection.synop-header-meta-synopsis">[meta.reflection.synop]
Header <code class="sourceCode cpp"><span class="op">&lt;</span>meta<span class="op">&gt;</span></code>
synopsis<span></span></a></li>
<li><a href="#meta.reflection.access.context-access-control-context" id="toc-meta.reflection.access.context-access-control-context">[meta.reflection.access.context]
Access control context<span></span></a></li>
<li><a href="#meta.reflection.access.queries-member-accessibility-queries" id="toc-meta.reflection.access.queries-member-accessibility-queries">[meta.reflection.access.queries]
Member accessibility queries<span></span></a></li>
<li><a href="#meta.reflection.member.queries-reflection-member-queries" id="toc-meta.reflection.member.queries-reflection-member-queries">[meta.reflection.member.queries]
Reflection member queries<span></span></a></li>
</ul></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">5</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" style="border-bottom:1px solid #cccccc" id="abstract"><span class="header-section-number">1</span> Abstract<a href="#abstract" class="self-link"></a></h1>
<p>We propose the addition of a <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>access_context</code>
type to <span class="citation" data-cites="P2996R8">[<a href="https://wg21.link/p2996r8" role="doc-biblioref">P2996R8</a>]</span> (“<em>Reflection for
C++26</em>”), which models the “context” (i.e., enclosing namespace,
class, or function) from which a class member is accessed.</p>
<p>An object of this type is proposed as a mandatory argument for the
<code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>members_of</code>
function, thereby allowing users to obtain only those class members that
are accessible from some context.</p>
<p>A “magical” <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>unchecked_access</code>
provides an <code class="sourceCode cpp">access_context</code> from
which all entities are accessible, thereby allowing “break glass” access
for use cases that require such superpowers, while also making such uses
easily audited (e.g., during code review) and clearly expressive of
their intent.</p>
<p>A family of additional APIs more fully integrates and harmonizes the
Reflection proposal with C++ access control. Notably, a <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>is_accessible</code>
function allows querying whether an entity is accessible from a context.
Additional utilities are proposed to allow libraries to discover whether
a class has inaccessible data members or bases without obtaining
reflections of those members in the first place.</p>
<p>Our proposal incorporates design elements from functions first
introduced by <span class="citation" data-cites="P2996R3">[<a href="https://wg21.link/p2996r3" role="doc-biblioref">P2996R3</a>]</span>, and iterated on through <span class="citation" data-cites="P2996R6">[<a href="https://wg21.link/p2996r6" role="doc-biblioref">P2996R6</a>]</span>, before being removed from
<span class="citation" data-cites="P2996R7">[<a href="https://wg21.link/p2996r7" role="doc-biblioref">P2996R7</a>]</span> due to unresolved design
elements around access to protected members (which we believe are
addressed by this proposal).</p>
<p>The intent of this proposal it to modify P2996 such that the changes
proposed here are considered concurrenty with any motion to integrate
P2996 into the Working Draft.</p>
<h1 data-number="2" style="border-bottom:1px solid #cccccc" id="background"><span class="header-section-number">2</span>
Background<a href="#background" class="self-link"></a></h1>
<h2 data-number="2.1" id="a-diversity-of-perspectives"><span class="header-section-number">2.1</span> A diversity of perspectives<a href="#a-diversity-of-perspectives" class="self-link"></a></h2>
<p>The discussion around whether reflection should be allowed to
introspect private class members is as old as the discussion around how
to bring reflection to C++. Within SG7, each such discussion has
affirmed the desire to:</p>
<ul>
<li>obtain reflections of all members of a reflected class,</li>
<li>query the properties of any reflected entity, and</li>
<li>refer to reflected entities directly via the “splicing” operator,
without recourse to name lookup or access control.</li>
</ul>
<p>This design direction is incorporated into the <span class="citation" data-cites="P2996R8">[<a href="https://wg21.link/p2996r8" role="doc-biblioref">P2996R8</a>]</span> (“<em>Reflection for
C++26</em>”) proposal currently targeting C++26.</p>
<ul>
<li>The <code class="sourceCode cpp">members_of</code> “metafunction”
returns a <code class="sourceCode cpp">vector</code> containing
reflections of <em>all</em> members of a class.</li>
<li>Predicates like <code class="sourceCode cpp">identifier_of</code>
and <code class="sourceCode cpp">type_of</code> can thereafter be used
to query properties of the reflected class members.</li>
<li>Splicing grants broad use of the member in many contexts (e.g.,
accessing the value of a static data member, forming a member access
expression, obtaining a pointer to member, etc).</li>
</ul>
<p>The topic was recently revisited at the 2024 Wrocław meeting, during
which a more fragmented set of perspectives within the broader WG21 body
came into focus.</p>
<ul>
<li>A significant contingent continues to express the position that a
permissive model for class introspection is an absolute requirement for
reflection.</li>
<li>A nontrivial number of voices raised concerns that users may be
surprised to obtain representations of private members, and that doing
so ought to be possible only when accompanied by a clear expression of
intent.</li>
<li>Some voices pointed out that, separately from the question of
whether it ought to be possible to reflect inaccessible members, it
certainly ought to be possible to obtain reflections of all members to
which the calling context <em>does</em> have access (i.e., “give me the
acccessible members”).</li>
<li>A small number of participants remain doubtful that any mechanism
should be provided that allows introspection of inaccessible
members.</li>
</ul>
<p>Though it appears regrettably impossible to make all parties happy
(since some perspectives listed above stand in diametric and
irreconcilable opposition), we believe that progress can be made to
address many of the concerns raised. In particular, we hope for this
paper to address the concerns of all but the last group mentioned
above.</p>
<h2 data-number="2.2" id="a-problem-of-composition"><span class="header-section-number">2.2</span> A problem of composition<a href="#a-problem-of-composition" class="self-link"></a></h2>
<p>Consider a simple hypothetical predicate that returns whether a class
member is accessible from the calling context.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> is_accessible<span class="op">(</span>info r<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span>;</span></code></pre></div>
<p>Such a function might be used as follows (using the syntax and
semantics of <span class="citation" data-cites="P2996R8">[<a href="https://wg21.link/p2996r8" role="doc-biblioref">P2996R8</a>]</span>):</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Cls <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> priv;</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>is_accessible<span class="op">(</span>members_of<span class="op">(^^</span>Cls<span class="op">)[</span><span class="dv">0</span><span class="op">]))</span>;</span></code></pre></div>
<p>This looks great! But it falls apart as soon a we try to build a
library on top of it.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> accessible_nsdms_of<span class="op">(</span>info cls<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  vector<span class="op">&lt;</span>info<span class="op">&gt;</span> result;</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> m <span class="op">:</span> nonstatic_data_members_of<span class="op">(</span>cls<span class="op">))</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>is_accessible<span class="op">(</span>m<span class="op">))</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>      result<span class="op">.</span>push_back<span class="op">(</span>m<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="cf">return</span> result;</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Cls <span class="op">{</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> priv;</span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">void</span> client<span class="op">()</span>;</span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> client<span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(</span>accessible_nsdms_of<span class="op">(^^</span>Cls<span class="op">).</span>size<span class="op">()</span> <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span>;  <span class="co">// fails</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The call to <code class="sourceCode cpp">is_accessible<span class="op">(</span>m<span class="op">)</span></code>
is considered from the context of the function
<code class="sourceCode cpp">accessible_nsdms_of</code> (which has no
privileged access to <code class="sourceCode cpp">Cls</code>), rather
than from the function <code class="sourceCode cpp"><span class="dt">void</span> client<span class="op">()</span></code>
(which does).</p>
<p>A different model is possible, which checks access from the “point
where constant evaluation begins” rather than from the point of call
(i.e., as proposed by <span class="citation" data-cites="P2996R3">[<a href="https://wg21.link/p2996r3" role="doc-biblioref">P2996R3</a>]</span>). Under this model,
accessibility is checked from <code class="sourceCode cpp"><span class="dt">void</span> client<span class="op">()</span></code>,
since the “outermost” expression under evaluation is the
<code class="sourceCode cpp"><em>constant-expression</em></code> of the
<code class="sourceCode cpp"><em>static_assert-declaration</em></code>
within that function. Although the assertion would pass under this
model, other cases become strange.</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">class</span> Cls <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> priv;</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="kw">consteval</span> <span class="dt">int</span> fn<span class="op">()</span>;</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">int</span> fn<span class="op">()</span> <span class="op">{</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> accessible_nsdms_of<span class="op">(^^</span>Cls<span class="op">).</span>size<span class="op">()</span>;</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> fn<span class="op">()</span>;  <span class="co">// returns 0</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Even though <code class="sourceCode cpp">fn</code> is a friend of
<code class="sourceCode cpp">Cls</code>, the constant evaluation begins
in <code class="sourceCode cpp">main</code>: The “point of constant
evaluation” model renders the friendship all but useless.</p>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="proposed-features"><span class="header-section-number">3</span>
Proposed features<a href="#proposed-features" class="self-link"></a></h1>
<h2 data-number="3.1" id="explicit-contexts"><span class="header-section-number">3.1</span> Explicit contexts<a href="#explicit-contexts" class="self-link"></a></h2>
<p>Rather than try to guess where access should be checked from, we
propose that it be specified explicitly.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Cls <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> priv;</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="kw">consteval</span> <span class="dt">int</span> fn<span class="op">()</span>;</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">int</span> fn<span class="op">()</span> <span class="op">{</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> accessible_nsdms_of<span class="op">(^^</span>Cls, std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>current<span class="op">()).</span>size<span class="op">()</span>;</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> fn<span class="op">()</span>;  <span class="co">// returns 1</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>accessible_nsdms_of<span class="op">(^^</span>Cls, std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>current<span class="op">())</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span>;</span></code></pre></div>
<p>The <code class="sourceCode cpp">access_context<span class="op">::</span>current<span class="op">()</span></code>
function returns a <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>access_context</code>
that represents the namespace, class, or function most nearly enclosing
the callsite. We propose two additional functions for obtaining an
<code class="sourceCode cpp">access_context</code>:</p>
<ul>
<li><code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>unprivileged<span class="op">()</span></code>
returns an <code class="sourceCode cpp">access_context</code>
representing unprivileged access (i.e., from the global namespace),
and</li>
<li><code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>unchecked<span class="op">()</span></code>
returns an <code class="sourceCode cpp">access_context</code> from which
all entities are unconditionally accessible.</li>
</ul>
<p>Values of type <code class="sourceCode cpp">access_context</code>
always originate from one of these three functions. In particular, there
is no mechanism for forging an
<code class="sourceCode cpp">access_context</code> that represents an
arbitrary (possibly more privileged) context.</p>
<h2 data-number="3.2" id="integrating-access-control-with-members_of"><span class="header-section-number">3.2</span> Integrating access control with
<code class="sourceCode cpp">members_of</code><a href="#integrating-access-control-with-members_of" class="self-link"></a></h2>
<p>We propose that the <code class="sourceCode cpp">std<span class="op">::</span>meta<span class="op">::</span>members_of</code>
interface require a second argument which specifies an access
context.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> members_of<span class="op">(</span>info cls, access_context ctx<span class="op">)</span> <span class="op">-&gt;</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span>;</span></code></pre></div>
<p>Note that the existing permissive semantics proposed by <span class="citation" data-cites="P2996R8">[<a href="https://wg21.link/p2996r8" role="doc-biblioref">P2996R8</a>]</span> can still be achieved through
use of <code class="sourceCode cpp">access_context<span class="op">::</span>unchecked<span class="op">()</span></code>.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> std<span class="op">::</span>meta<span class="op">::</span>access_context;</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Cls <span class="op">{</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">int</span> priv <span class="op">=</span> <span class="dv">42</span>;</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> std<span class="op">::</span>meta<span class="op">::</span>info m <span class="op">=</span> members_of<span class="op">(^^</span>Cls, access_context<span class="op">::</span>unchecked<span class="op">())[</span><span class="dv">0</span><span class="op">]</span>;</span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>identifier_of<span class="op">(</span>m<span class="op">)</span> <span class="op">==</span> <span class="st">&quot;priv&quot;</span><span class="op">)</span>;</span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">([:</span>m<span class="op">:]</span> <span class="op">==</span> <span class="dv">42</span><span class="op">)</span>;</span></code></pre></div>
<p>whereas library functions that respect access are now easy to write
and to compose.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> constructors_of<span class="op">(</span>std<span class="op">::</span>meta<span class="op">::</span>info cls,</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>                               std<span class="op">::</span>meta<span class="op">::</span>access_context ctx<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> std<span class="op">::</span>vector<span class="op">(</span>std<span class="op">::</span>from_range,</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>                     members_of<span class="op">(</span>cls, ctx<span class="op">)</span> <span class="op">|</span> std<span class="op">::</span>meta<span class="op">::</span>is_constructor<span class="op">)</span>;</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Better still, writing the function once gives mechanisms for
obtaining public members, accessible members, and all members. We
therefore propose the removal of the
<code class="sourceCode cpp">get_public_members</code> family of
functions that was added in <span class="citation" data-cites="P2996R7">[<a href="https://wg21.link/p2996r7" role="doc-biblioref">P2996R7</a>]</span> whose sole purpose was to
provide a more constrained alternative to
<code class="sourceCode cpp">members_of</code>: With this proposal,
these functions are exactly equivalent to calling
<code class="sourceCode cpp">members_of</code> with the <code class="sourceCode cpp">access_context<span class="op">::</span>unprivileged<span class="op">()</span></code>
access context.</p>
<p>Perhaps unsurprisingly, we propose the same changes to
<code class="sourceCode cpp">bases_of</code> and also propose the
removal of <code class="sourceCode cpp">get_public_bases</code>.</p>
<h2 data-number="3.3" id="modeling-protected-access"><span class="header-section-number">3.3</span> Modeling protected access<a href="#modeling-protected-access" class="self-link"></a></h2>
<p>When accessing a protected member or base, more complex rules apply:
The class whose scope the name is looked up in (i.e., the “naming
class”) must also be specified. For instance, given the classes</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Base <span class="op">{</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="kw">protected</span><span class="op">:</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> prot;</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Derived <span class="op">:</span> Base <span class="op">{</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> fn<span class="op">()</span>;</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>the definition of
<code class="sourceCode cpp">Derived<span class="op">::</span>fn</code>
is allowed to reference the
<code class="sourceCode cpp">prot</code>-subobject of
<code class="sourceCode cpp">Derived</code>, i.e.,</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">this</span><span class="op">-&gt;</span>prot <span class="op">=</span> <span class="dv">42</span>;</span></code></pre></div>
<p>because the name <code class="sourceCode cpp">prot</code> is “looked
up in the scope” of <code class="sourceCode cpp">Derived</code>. But it
is <em>not</em> permitted to form a pointer-to-member:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> mptr <span class="op">=</span> <span class="op">&amp;</span>Base<span class="op">::</span>prot;</span></code></pre></div>
<p>which requires performing a search for the name
<code class="sourceCode cpp">prot</code> in the scope of
<code class="sourceCode cpp">Base</code>.</p>
<p>The inability to model these semantics is what resulted in the
removal of the <code class="sourceCode cpp">access_context</code> API
from <span class="citation" data-cites="P2996R7">[<a href="https://wg21.link/p2996r7" role="doc-biblioref">P2996R7</a>]</span>. To resolve this, we propose a
member function <code class="sourceCode cpp">access_context<span class="op">::</span>via<span class="op">(</span>info<span class="op">)</span></code>
that facilitates the explicit specification of a naming class.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> Derived<span class="op">::</span>fn<span class="op">()</span> <span class="op">{</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> std<span class="op">::</span>meta<span class="op">::</span>access_context;</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> ctx1 <span class="op">=</span> access_context<span class="op">::</span>current<span class="op">()</span>;</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> ctx2 <span class="op">=</span> ctx1<span class="op">.</span>via<span class="op">(^^</span>Derived<span class="op">)</span>;</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(</span>nonstatic_data_members_of<span class="op">(^^</span>Base, ctx1<span class="op">).</span>size<span class="op">()</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span>;</span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// &quot;naming class&quot; defaults to &#39;Base&#39;; &#39;prot&#39; is inaccessible as &#39;Base::prot&#39;.</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_assert</span><span class="op">(</span>nonstatic_data_members_of<span class="op">(^^</span>Base, ctx2<span class="op">).</span>size<span class="op">()</span> <span class="op">==</span> <span class="dv">1</span><span class="op">)</span>;</span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>    <span class="co">// OK, &quot;naming class&quot; is &#39;Derived&#39;; &#39;prot&#39; is &quot;named via the class&quot; &#39;Derived&#39;.</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>With this addition, we can fully model access checking in C++. A
sketch of our <code class="sourceCode cpp">access_context</code> class
(as implemented by Bloomberg’s experimental <a href="https://github.com/bloomberg/clang-p2996">Clang/P2996</a> fork) is
as follows:</p>
<div class="std">
<blockquote>
<div class="addu">
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> access_context <span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> access_context<span class="op">(</span>info scope, info naming_class<span class="op">)</span> <span class="kw">noexcept</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>      <span class="op">:</span> scope<span class="op">{</span>scope<span class="op">}</span>, naming_class<span class="op">{</span>naming_class<span class="op">}</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> info scope;  <span class="co">// exposition only</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> info naming_class;  <span class="co">// exposition only</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> access_context<span class="op">()</span> <span class="kw">noexcept</span> <span class="op">:</span> scope<span class="op">{^^::}</span>, naming_class<span class="op">{}</span> <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> access_context<span class="op">(</span><span class="kw">const</span> access_context <span class="op">&amp;)</span> <span class="kw">noexcept</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> access_context<span class="op">(</span>access_context <span class="op">&amp;&amp;)</span> <span class="kw">noexcept</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">consteval</span> access_context current<span class="op">()</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">{</span>__metafunction<span class="op">(</span>detail<span class="op">::</span>__metafn_access_context<span class="op">)</span>, <span class="op">{}}</span>;</span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">consteval</span> access_context unprivileged<span class="op">()</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> access_context<span class="op">{}</span>;</span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">consteval</span> access_context unchecked<span class="op">()</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> access_context<span class="op">{{}</span>, <span class="op">{}}</span>;</span>
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb13-24"><a href="#cb13-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-25"><a href="#cb13-25" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> access_context via<span class="op">(</span>info cls<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb13-26"><a href="#cb13-26" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(!</span>is_class_type<span class="op">(</span>cls<span class="op">))</span></span>
<span id="cb13-27"><a href="#cb13-27" aria-hidden="true" tabindex="-1"></a>      <span class="cf">throw</span> <span class="st">&quot;naming class must be a reflection of a class type&quot;</span>;</span>
<span id="cb13-28"><a href="#cb13-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-29"><a href="#cb13-29" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> access_context<span class="op">{</span>scope, cls<span class="op">}</span>;</span>
<span id="cb13-30"><a href="#cb13-30" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb13-31"><a href="#cb13-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</div>
</blockquote>
</div>
<h2 data-number="3.4" id="additional-facilities"><span class="header-section-number">3.4</span> Additional facilities<a href="#additional-facilities" class="self-link"></a></h2>
<p>It may be desireable for a library to determine whether a provided
<code class="sourceCode cpp">access_context</code> is sufficiently
privileged to observe the whole object representation of instances of a
given class. This is easily accomplished by composing
<code class="sourceCode cpp">members_of</code> and
<code class="sourceCode cpp">bases_of</code> with
<code class="sourceCode cpp">is_accessible</code>:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> has_inaccessible_nonstatic_data_members<span class="op">(</span>info cls,</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>                                                       access_contxt ctx<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span> <span class="op">{</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="op">!</span>std<span class="op">::</span>ranges<span class="op">::</span>all_of<span class="op">(</span>members_of<span class="op">(</span>cls, std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>unchecked<span class="op">())</span>,</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>                              <span class="op">[=](</span>info r<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> is_accessible<span class="op">(</span>r, ctx<span class="op">)</span>; <span class="op">})</span>;</span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> has_inaccessible_bases<span class="op">(</span>info cls, access_contxt ctx<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span> <span class="op">{</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="op">!</span>std<span class="op">::</span>ranges<span class="op">::</span>all_of<span class="op">(</span>bases_of<span class="op">(</span>cls, std<span class="op">::</span>meta<span class="op">::</span>access_context<span class="op">::</span>unchecked<span class="op">())</span>,</span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>                              <span class="op">[=](</span>info r<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> is_accessible<span class="op">(</span>r, ctx<span class="op">)</span>; <span class="op">})</span>;</span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>That said, some library authors have asked for this capability to be
made available through the standard library such that clients have no
need to handle reflections of inaccessible members at all. We therefore
propose that the above functions also be augmented to P2996.</p>
<h2 data-number="3.5" id="a-stronger-notion-of-access-control-for-reflection"><span class="header-section-number">3.5</span> A stronger notion of access
control for reflection<a href="#a-stronger-notion-of-access-control-for-reflection" class="self-link"></a></h2>
<p>Previous proposals (<span class="citation" data-cites="P3451R0">[<a href="https://wg21.link/p3451r0" role="doc-biblioref">P3451R0</a>]</span>, <span class="citation" data-cites="P3473R0">[<a href="https://wg21.link/p3473r0" role="doc-biblioref">P3473R0</a>]</span>) have suggested integrating
access control with Reflection by checking access at splice-time. If
one’s goal is to prevent introspection of inaccessible member
subobjects, then such a change is not enough: <span class="citation" data-cites="P2996R8">[<a href="https://wg21.link/p2996r8" role="doc-biblioref">P2996R8</a>]</span> is replete with metafunctions
that, once one has a reflection, can be used to circumvent access
control: <code class="sourceCode cpp">value_of</code>,
<code class="sourceCode cpp">object_of</code>,
<code class="sourceCode cpp">template_arguments_of</code>,
<code class="sourceCode cpp">extract</code>,
<code class="sourceCode cpp">define_aggregate</code>, and
<code class="sourceCode cpp">substitute</code> can all be creatively
applied to circumvent access control to various extents without ever
having to splice the reflection.</p>
<p>This proposal, therefore, presents a stronger notion of access
control by making it straightforward to avoid getting reflections of
inaccessible members in the first place. Like <span class="citation" data-cites="P3451R0">[<a href="https://wg21.link/p3451r0" role="doc-biblioref">P3451R0</a>]</span>, we propose a “break glass”
mechanism (i.e., <code class="sourceCode cpp">access_context<span class="op">::</span>unchecked<span class="op">()</span></code>)
for obtaining unconditional access to a member (e.g., to dump a debug
representation of an object to
<code class="sourceCode cpp">stdout</code>), and like that paper, the
mechanism is trivially auditable (e.g.,
<code class="sourceCode cpp">grep unchecked_access</code>). The use of
<code class="sourceCode cpp">unchecked_access</code> is deliberately
<strong>loud</strong> and <strong>unambiguous</strong> in its meaning:
It is very difficult to misconstrue what the author of the code
intended, and hard to imagine that they will be surprised to find
inaccessible members in the resulting
<code class="sourceCode cpp">vector</code>.</p>
<p>Revisiting the multitude of perspectives observed within WG21, we
believe this proposal should make participants with the following views
happy:</p>
<ul>
<li>those who want a permissive model for class introspection,</li>
<li>those concerned that users may be surprised to obtain
representations of private members,</li>
<li>those who want inaccessible members to only be returned when
accompanied by a clear expression of intent, and</li>
<li>those who want to obtain reflections of all accessible members, and
to check whether a given member is accessible.</li>
</ul>
<p>We believe that the union of these groups represent an overwhelming
majority within WG21 and within the broader C++ community.</p>
<h2 data-number="3.6" id="implementation-experience"><span class="header-section-number">3.6</span> Implementation experience<a href="#implementation-experience" class="self-link"></a></h2>
<p>All features proposed here are implemented by Bloomberg’s
experimental <a href="https://github.com/bloomberg/clang-p2996">Clang/P2996</a> fork.
They are enabled with the <code class="sourceCode cpp"><span class="op">-</span>faccess<span class="op">-</span>contexts</code>
flag (or <code class="sourceCode cpp"><span class="op">-</span>freflection<span class="op">-</span>latest</code>).</p>
<h1 data-number="4" style="border-bottom:1px solid #cccccc" id="proposed-wording"><span class="header-section-number">4</span>
Proposed wording<a href="#proposed-wording" class="self-link"></a></h1>
<p><span class="draftnote" style="color: #01796F">[ Drafting note: All
wording assumes the changes proposed by <span class="citation" data-cites="P2996R8">[<a href="https://wg21.link/p2996r8" role="doc-biblioref">P2996R8</a>]</span>. The following affects only the
library; no core language changes are required. Our intent is to modify
the text of P2996 itself such that the changes proposed here are
considered concurrently with any motion to integrate P2996 into the
Working Draft. ]</span></p>
<h2 class="unnumbered" id="meta.reflection.synop-header-meta-synopsis">[meta.reflection.synop]
Header <code class="sourceCode cpp"><span class="op">&lt;</span>meta<span class="op">&gt;</span></code>
synopsis<a href="#meta.reflection.synop-header-meta-synopsis" class="self-link"></a></h2>
<p>Modify the synopsis of <code class="sourceCode cpp"><span class="op">&lt;</span>meta<span class="op">&gt;</span></code>
as follows:</p>
<div class="std">
<blockquote>
<p><strong>Header <code class="sourceCode cpp"><span class="op">&lt;</span>meta<span class="op">&gt;</span></code>
synopsis</strong></p>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;initializer_list&gt;</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> info <span class="op">=</span> <span class="kw">decltype</span><span class="op">(^^::)</span>;</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">[...]</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> info template_of<span class="op">(</span>info r<span class="op">)</span>;</span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> template_arguments_of<span class="op">(</span>info r<span class="op">)</span>;</span></code></pre></div>
<div class="addu">
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [meta.reflection.access.context], access control context</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>  </span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> access_context <span class="op">{</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">consteval</span> access_context current<span class="op">()</span> <span class="kw">noexcept</span>;</span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">consteval</span> access_context unprivileged<span class="op">()</span> <span class="kw">noexcept</span>;</span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">consteval</span> access_context unchecked<span class="op">()</span> <span class="kw">noexcept</span>;</span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">consteval</span> access_context via<span class="op">(</span>info cls<span class="op">)</span> <span class="kw">const</span>;</span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> info <em>scope</em> <span class="op">=</span> <span class="op">^^::</span>;  <span class="co">// exposition only</span></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> info <em>naming_class</em> <span class="op">=</span> <span class="op">{}</span>;  <span class="co">// exposition only</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [meta.reflection.access.queries], member accessessibility queries</span></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="dt">bool</span> is_accessible<span class="op">(</span>info r, access_context ctx<span class="op">)</span>;</span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="dt">bool</span> has_inaccessible_nonstatic_data_members<span class="op">(</span></span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>      info r,</span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>      access_context ctx<span class="op">)</span>;</span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> <span class="dt">bool</span> has_inaccessible_bases<span class="op">(</span>info r, access_context ctx<span class="op">)</span>;</span></code></pre></div>
</div>
<div class="sourceCode" id="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [meta.reflection.member.queries], reflection member queries</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> members_of<span class="op">(</span>info r<span class="addu"><code class="sourceCode cpp">,</code> </span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>                                    <span class="addu"><code class="sourceCode cpp">access_context ctx</code></span><span class="op">)</span>;</span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> bases_of<span class="op">(</span>info type<span class="addu"><code class="sourceCode cpp">,</code> </span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>                                  <span class="addu"><code class="sourceCode cpp">access_context ctx</code></span><span class="op">)</span>;</span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> static_data_members_of<span class="op">(</span>info type<span class="addu"><code class="sourceCode cpp">,</code> </span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>                                                <span class="addu"><code class="sourceCode cpp">access_context ctx</code></span><span class="op">)</span>;</span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> nonstatic_data_members_of<span class="op">(</span>info type<span class="addu"><code class="sourceCode cpp">,</code> </span></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a>                                                   <span class="addu"><code class="sourceCode cpp">access_context ctx</code></span><span class="op">)</span>;</span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> enumerators_of<span class="op">(</span>info type_enum<span class="op">)</span>;</span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">consteval vector&lt;info&gt; get_public_members(info type);</code></span></del></span></span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">consteval vector&lt;info&gt; get_public_bases(info type);</code></span></del></span></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">consteval vector&lt;info&gt; get_public_static_data_members(info type);</code></span></del></span></span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">consteval vector&lt;info&gt; get_public_nonstatic_data_members(info type);</code></span></del></span></span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<h2 class="unnumbered" id="meta.reflection.access.context-access-control-context">[meta.reflection.access.context]
Access control context<a href="#meta.reflection.access.context-access-control-context" class="self-link"></a></h2>
<p>Add a new subsection after [meta.reflection.queries]:</p>
<div class="std">
<blockquote>
<div class="addu">
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_1" id="pnum_1">1</a></span>
The <code class="sourceCode cpp">access_context</code> class is a
structural type that represents a namespace, class, or function from
which queries pertaining to access rules may be performed, as well as
the naming class ([class.access.base]), if any.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> access_context access_context<span class="op">::</span>current<span class="op">()</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_2" id="pnum_2">2</a></span>
Let <code class="sourceCode cpp"><em>P</em></code> be the program point
at which <code class="sourceCode cpp">access_context<span class="op">::</span>current<span class="op">()</span></code>
is called.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_3" id="pnum_3">3</a></span>
<em>Returns</em>: An <code class="sourceCode cpp">access_context</code>
whose <code class="sourceCode cpp"><em>naming_class</em></code> is the
null reflection and whose
<code class="sourceCode cpp"><em>scope</em></code> is the unique
namespace, class, or function whose associated scope
<code class="sourceCode cpp"><em>S</em></code> encloses
<code class="sourceCode cpp"><em>P</em></code> and for which no other
scope intervening between <code class="sourceCode cpp"><em>P</em></code>
and <code class="sourceCode cpp"><em>S</em></code> is the scope
associated with a namespace, class, or function.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> access_context access_context<span class="op">::</span>unprivileged<span class="op">()</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_4" id="pnum_4">4</a></span>
<em>Returns</em>: An <code class="sourceCode cpp">access_context</code>
whose <code class="sourceCode cpp"><em>naming_class</em></code> is the
null reflection and whose
<code class="sourceCode cpp"><em>scope</em></code> is the global
namespace.</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> access_context access_context<span class="op">::</span>unchecked<span class="op">()</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_5" id="pnum_5">5</a></span>
<em>Returns</em>: An <code class="sourceCode cpp">access_context</code>
whose <code class="sourceCode cpp"><em>naming_class</em></code> and
<code class="sourceCode cpp"><em>scope</em></code> are both the null
reflection.</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> access_context access_context<span class="op">::</span>via<span class="op">(</span>info cls<span class="op">)</span> <span class="kw">const</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_6" id="pnum_6">6</a></span>
<em>Constant When</em>: <code class="sourceCode cpp">cls</code>
represents a class type.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_7" id="pnum_7">7</a></span>
<em>Returns</em>: An <code class="sourceCode cpp">access_context</code>
whose <code class="sourceCode cpp"><em>scope</em></code> is <code class="sourceCode cpp"><span class="kw">this</span><span class="op">-&gt;</span><em>scope</em></code>
and whose <code class="sourceCode cpp"><em>naming_class</em></code> is
<code class="sourceCode cpp">cls</code>.</p>
</div>
</blockquote>
</div>
<h2 class="unnumbered" id="meta.reflection.access.queries-member-accessibility-queries">[meta.reflection.access.queries]
Member accessibility queries<a href="#meta.reflection.access.queries-member-accessibility-queries" class="self-link"></a></h2>
<p>Add a new subsection after [meta.reflection.access.context]:</p>
<div class="std">
<blockquote>
<div class="addu">
<div class="sourceCode" id="cb22"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> is_accessible<span class="op">(</span>info r, access_context ctx<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_8" id="pnum_8">1</a></span>
Let <code class="sourceCode cpp"><em>P</em></code> be a program point
that occurs in the definition of the entity represented by
<code class="sourceCode cpp">ctx<span class="op">.</span><em>scope</em></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_9" id="pnum_9">2</a></span>
<em>Returns</em>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_10" id="pnum_10">3</a></span>
If
<code class="sourceCode cpp">ctx<span class="op">.</span><em>scope</em></code>
represents the null reflection, then
<code class="sourceCode cpp"><span class="kw">true</span></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_11" id="pnum_11">4</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents a member
of a class <code class="sourceCode cpp"><em>C</em></code>, then
<code class="sourceCode cpp"><span class="kw">true</span></code> if that
class member is accessible at
<code class="sourceCode cpp"><em>P</em></code> ([class.access.base])
when named in either
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_12" id="pnum_12">(4.1)</a></span>
<code class="sourceCode cpp">C</code> if <code class="sourceCode cpp">ctx<span class="op">.</span><em>naming_class</em></code>
is the null reflection, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_13" id="pnum_13">(4.2)</a></span>
the class represented by <code class="sourceCode cpp">ctx<span class="op">.</span><em>naming_classs</em></code>
otherwise.</li>
</ul></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_14" id="pnum_14">5</a></span>
Otherwise, if <code class="sourceCode cpp">r</code> represents a direct
base class relationship between a base class
<code class="sourceCode cpp"><em>B</em></code> and a derived class
<code class="sourceCode cpp"><em>D</em></code>, then
<code class="sourceCode cpp"><span class="kw">true</span></code> if the
base class <code class="sourceCode cpp"><em>B</em></code> of
<code class="sourceCode cpp"><em>D</em></code> is accessible at
<code class="sourceCode cpp"><em>P</em></code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_15" id="pnum_15">6</a></span>
Otherwise,
<code class="sourceCode cpp"><span class="kw">true</span></code>.</li>
</ul>
<div class="note">
<p><span>[ <em>Note 1:</em> </span>The definitions of when a class
member or base class are accessible from a point
<code class="sourceCode cpp"><em>P</em></code> do not consider whether a
declaration of that entity is reachable from
<code class="sourceCode cpp"><em>P</em></code>.<span> — <em>end
note</em> ]</span></p>
</div>
<div class="example">
<span>[ <em>Example 1:</em> </span>
<div class="sourceCode" id="cb23"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> access_context fn<span class="op">()</span> <span class="op">{</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> access_context<span class="op">::</span>current<span class="op">()</span>;</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Cls <span class="op">{</span></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> mem;</span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">consteval</span> access_context fn<span class="op">()</span>;</span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb23-9"><a href="#cb23-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> r <span class="op">=</span> <span class="op">^^</span>mem;</span>
<span id="cb23-10"><a href="#cb23-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb23-11"><a href="#cb23-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-12"><a href="#cb23-12" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>is_accessible<span class="op">(</span>Cls<span class="op">::</span>r, fn<span class="op">()))</span>;  <span class="co">// OK</span></span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>
<div class="sourceCode" id="cb24"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_inaccessible_nonstatic_data_members<span class="op">(</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>      info r,</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>      access_context ctx<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_16" id="pnum_16">7</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">is_accessible<span class="op">(</span><em>R</em>, ctx<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">false</span></code> for
any <code class="sourceCode cpp"><em>R</em></code> in <code class="sourceCode cpp">members_of<span class="op">(</span>r, access_context<span class="op">::</span>unchecked<span class="op">())</span></code>.
Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> has_inaccessible_bases<span class="op">(</span>info r, access_context ctx<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_17" id="pnum_17">8</a></span>
<em>Returns</em>:
<code class="sourceCode cpp"><span class="kw">true</span></code> if
<code class="sourceCode cpp">is_accessible<span class="op">(</span><em>R</em>, ctx<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">false</span></code> for
any <code class="sourceCode cpp"><em>R</em></code> in <code class="sourceCode cpp">bases_of<span class="op">(</span>r, access_context<span class="op">::</span>unchecked<span class="op">())</span></code>.
Otherwise,
<code class="sourceCode cpp"><span class="kw">false</span></code>.</p>
</div>
</blockquote>
</div>
<h2 class="unnumbered" id="meta.reflection.member.queries-reflection-member-queries">[meta.reflection.member.queries]
Reflection member queries<a href="#meta.reflection.member.queries-reflection-member-queries" class="self-link"></a></h2>
<p>Modify the signature of
<code class="sourceCode cpp">members_of</code> that precedes paragraph 1
as follows:</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> members_of<span class="op">(</span>info r<span class="addu"><code class="sourceCode cpp">,</code> </span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>                                  <span class="addu"><code class="sourceCode cpp">access_context ctx</code></span><span class="op">)</span>;</span></code></pre></div>
<p>Modify paragraph 4 as follows:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_18" id="pnum_18">4</a></span>
<em>Returns</em>: A <code class="sourceCode cpp">vector</code>
containing reflections of all members-of-representable members of the
entity represented by <code class="sourceCode cpp">r</code> that are
members-of-reachable from some point in the evaluation context <span class="addu">for which the reflection
<code class="sourceCode cpp"><em>R</em></code> satisfies <code class="sourceCode cpp">is_accessible<span class="op">(</span><em>R</em>, ctx<span class="op">)</span></code></span>.
If <code class="sourceCode cpp"><em>E</em></code> represents a class
<code class="sourceCode cpp"><em>C</em></code>, then the vector also
contains reflections representing all unnamed bit-fields declared within
the member-specification of
<code class="sourceCode cpp"><em>C</em></code> <span class="addu">for
which the reflection <code class="sourceCode cpp"><em>R</em></code>
satisfies <code class="sourceCode cpp">is_accessible<span class="op">(</span><em>R</em>, ctx<span class="op">)</span></code></span>.
Class members and unnamed bit-fields are indexed in the order in which
they are declared, but the order of namespace members is unspecified.
<span class="note"><span>[ <em>Note 1:</em> </span>Base classes are not
members. Implicitly-declared special members appear after any
user-declared members.<span> — <em>end note</em> ]</span></span></p>
</blockquote>
</div>
<p>Modify the signature of <code class="sourceCode cpp">bases_of</code>
that follows paragraph 4 as follows:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb27"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> bases_of<span class="op">(</span>info type<span class="addu"><code class="sourceCode cpp">,</code> </span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>                                <span class="addu"><code class="sourceCode cpp">access_context ctx</code></span><span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Modify paragraph 6 as follows:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_19" id="pnum_19">5</a></span>
<em>Returns</em>: Let <code class="sourceCode cpp">C</code> be the type
represented by <code class="sourceCode cpp">dealias<span class="op">(</span>type<span class="op">)</span></code>.
A <code class="sourceCode cpp">vector</code> containing the reflections
of all the direct base class relationships, if any, of
<code class="sourceCode cpp">C</code> <span class="addu">for which the
reflection <code class="sourceCode cpp"><em>R</em></code> satisfies
<code class="sourceCode cpp">is_accessible<span class="op">(</span><em>R</em>, ctx<span class="op">)</span></code></span>.
The direct base class relationships are indexed in the order in which
the corresponding base classes appear in the
<em>base-specifier-list</em> of
<code class="sourceCode cpp">C</code>.</p>
</blockquote>
</div>
<p>Modify the signature of
<code class="sourceCode cpp">static_data_members_of</code> that follows
paragraph 6 as follows:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb28"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> static_data_members_of<span class="op">(</span>info type<span class="addu"><code class="sourceCode cpp">,</code> </span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>                                              <span class="addu"><code class="sourceCode cpp">access_context ctx</code></span><span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Modify paragraph 8 as follows:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_20" id="pnum_20">6</a></span>
<em>Returns</em>: A <code class="sourceCode cpp">vector</code>
containing each element <code class="sourceCode cpp">e</code> of <code class="sourceCode cpp">members_of<span class="op">(</span>type</code><span class="addu"><code class="sourceCode cpp">, ctx</code></span><code class="sourceCode cpp"><span class="op">)</span></code>
such that <code class="sourceCode cpp">is_variable<span class="op">(</span>e<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>, in
order.</p>
</blockquote>
</div>
<p>Modify the signature of
<code class="sourceCode cpp">nonstatic_data_members_of</code> that
follows paragraph 8 as follows:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb29"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> vector<span class="op">&lt;</span>info<span class="op">&gt;</span> nonstatic_data_members_of<span class="op">(</span>info type<span class="addu"><code class="sourceCode cpp">,</code> </span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>                                                 <span class="addu"><code class="sourceCode cpp">access_context ctx</code></span><span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Modify paragraph 10 as follows:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_21" id="pnum_21">10</a></span>
<em>Returns</em>: A <code class="sourceCode cpp">vector</code>
containing each element <code class="sourceCode cpp">e</code> of <code class="sourceCode cpp">members_of<span class="op">(</span>type</code><span class="addu"><code class="sourceCode cpp">, ctx</code></span><code class="sourceCode cpp"><span class="op">)</span></code>
such that <code class="sourceCode cpp">is_nonstatic_data_member<span class="op">(</span>e<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>, in
order.</p>
</blockquote>
</div>
<p>Strike everything after paragraph 12 from the section:</p>
<div class="std">
<blockquote>
<div class="rm" style="color: #bf0303">

<div class="sourceCode" id="cb30"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a>consteval vector&lt;info&gt; get_public_members(info type);</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_22" id="pnum_22">11</a></span>
<em>Constant When</em>:
<code class="sourceCode default">dealias(type)</code> represents a
complete class type.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_23" id="pnum_23">12</a></span>
<em>Returns</em>: A <code class="sourceCode default">vector</code>
containing each element <code class="sourceCode default">e</code> of
<code class="sourceCode default">members_of(type)</code> such that
<code class="sourceCode default">is_public(e)</code> is
<code class="sourceCode default">true</code>, in order.</p>
<div class="sourceCode" id="cb31"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a>consteval vector&lt;info&gt; get_public_bases(info type);</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_24" id="pnum_24">13</a></span>
<em>Constant When</em>:
<code class="sourceCode default">dealias(type)</code> represents a
complete class type.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_25" id="pnum_25">14</a></span>
<em>Returns</em>: A <code class="sourceCode default">vector</code>
containing each element <code class="sourceCode default">e</code> of
<code class="sourceCode default">bases_of(type)</code> such that
<code class="sourceCode default">is_public(e)</code> is
<code class="sourceCode default">true</code>, in order.</p>
<div class="sourceCode" id="cb32"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a>consteval vector&lt;info&gt; get_public_static_data_members(info type);</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_26" id="pnum_26">15</a></span>
<em>Constant When</em>:
<code class="sourceCode default">dealias(type)</code> represents a
complete class type.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_27" id="pnum_27">16</a></span>
<em>Returns</em>: A <code class="sourceCode default">vector</code>
containing each element <code class="sourceCode default">e</code> of
<code class="sourceCode default">static_data_members_of(type)</code>
such that <code class="sourceCode default">is_public(e)</code> is
<code class="sourceCode default">true</code>, in order.</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a>consteval vector&lt;info&gt; get_public_nonstatic_data_members(info type);</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_28" id="pnum_28">17</a></span>
<em>Constant When</em>:
<code class="sourceCode default">dealias(type)</code> represents a
complete class type.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_29" id="pnum_29">18</a></span>
<em>Returns</em>: A <code class="sourceCode default">vector</code>
containing each element <code class="sourceCode default">e</code> of
<code class="sourceCode default">nonstatic_data_members_of(type)</code>
such that <code class="sourceCode default">is_public(e)</code> is
<code class="sourceCode default">true</code>, in order.</p>
</div>
</blockquote>
</div>
<h1 data-number="5" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">5</span>
References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="1" role="doc-bibliography">
<div id="ref-P2996R3" class="csl-entry" role="doc-biblioentry">
[P2996R3] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde, Dan Katz. 2024-05-22. Reflection for
C++26. <a href="https://wg21.link/p2996r3"><div class="csl-block">https://wg21.link/p2996r3</div></a>
</div>
<div id="ref-P2996R6" class="csl-entry" role="doc-biblioentry">
[P2996R6] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde, Dan Katz. 2024-10-10. Reflection for
C++26. <a href="https://wg21.link/p2996r6"><div class="csl-block">https://wg21.link/p2996r6</div></a>
</div>
<div id="ref-P2996R7" class="csl-entry" role="doc-biblioentry">
[P2996R7] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde, Dan Katz. 2024-10-13. Reflection for
C++26. <a href="https://wg21.link/p2996r7"><div class="csl-block">https://wg21.link/p2996r7</div></a>
</div>
<div id="ref-P2996R8" class="csl-entry" role="doc-biblioentry">
[P2996R8] Barry Revzin, Wyatt Childers, Peter Dimov, Andrew Sutton,
Faisal Vali, Daveed Vandevoorde, Dan Katz. 2024-12-16. Reflection for
C++26. <a href="https://wg21.link/p2996r8"><div class="csl-block">https://wg21.link/p2996r8</div></a>
</div>
<div id="ref-P3451R0" class="csl-entry" role="doc-biblioentry">
[P3451R0] Barry Revzin. 2024-10-14. A Suggestion for Reflection Access
Control. <a href="https://wg21.link/p3451r0"><div class="csl-block">https://wg21.link/p3451r0</div></a>
</div>
<div id="ref-P3473R0" class="csl-entry" role="doc-biblioentry">
[P3473R0] Steve Downey. 2024-10-16. Splicing Should Respect Access
Control. <a href="https://wg21.link/p3473r0"><div class="csl-block">https://wg21.link/p3473r0</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
