<!DOCTYPE html>
<html lang="en"><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<style>
pre {font-family: "Consolas", "Lucida Console", monospace; margin-left:20pt; }
code {font-family: "Consolas", "Lucida Console", monospace; }
pre > i   { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
code > i  { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
pre > em  { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
code > em { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
dl > dt { font-style:italic; }
body { font-family: "Calibri" }

@media (prefers-color-scheme: dark) {
	body { background: #111; color:  #ccc; }
	a { color:  #38f; }
	a:visited { color:  #a4d; }
	.sect { color:  #ccc; }
    del { text-decoration: line-through; color: #EE9999; }
    ins { text-decoration: underline; color: #99EE99; }
    blockquote.std    { color: #ccc; background-color: #2A2A2A;  border: 1px solid #3A3A3A;  padding-left: 0.5em; padding-right: 0.5em; }
    blockquote.stddel { text-decoration: line-through;  color: #ccc; background-color: #221820;  border: 1px solid #332228;  padding-left: 0.5em; padding-right: 0.5em; ; }
    blockquote.stdins { text-decoration: underline;  color: #ccc; background-color: #182220;  border: 1px solid #223328; padding: 0.5em; }
    table { border: 1px solid #ccc; border-spacing: 0px;  margin-left: auto; margin-right: auto; }
}

@media (prefers-color-scheme: light) {
	body { background:  white; color: black; }
    del { text-decoration: line-through; color: #8B0040; }
    ins { text-decoration: underline; color: #005100; }
    blockquote.std    { color: #000000; background-color: #F1F1F1;  border: 1px solid #D1D1D1;  padding-left: 0.5em; padding-right: 0.5em; }
    blockquote.stddel { text-decoration: line-through;  color: #000000; background-color: #FFEBFF;  border: 1px solid #ECD7EC;  padding-left: 0.5em; padding-right: 0.5em; ; }
    blockquote.stdins { text-decoration: underline;  color: #000000; background-color: #C8FFC8;  border: 1px solid #B3EBB3; padding: 0.5em; }
    table { border: 1px solid black; border-spacing: 1px;  margin-left: auto; margin-right: auto; }
}


.comment em { font-family: "Calibri"; font-style:italic; }
p.example   { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }
div.poll { margin-left: 2em; }

code.extract { background-color: #F5F6A2; }
pre.extract  { margin-left: 2em; background-color: #F5F6A2;  border: 1px solid #E1E28E; }

p.function    { }
.attribute    { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;  padding-right: 1ex; }
.attribute dd { margin-left: 0em; }

.editor { color: #4444BB; font-style: normal; background-color: #DDDDDD; }

tab { padding-left: 4em; }
tab3 { padding-left: 3em; }

.link { float: right; font-family: "Consolas", "Lucida Console", monospace; font-size:80% }


table.header { border: none; border-spacing: 0;  margin-left: 0px; font-style: normal; }
td.header { border: none; border-spacing: 0;  margin-left: 0px; font-style: normal; }
.header { border: none; border-spacing: 0;  margin-left: 0px; font-style: normal; }
table.poll { border: 1px solid black; border-spacing: 0px;  margin-left: 0px; font-style: normal; }

th { text-align: left; vertical-align: top;  padding-left: 0.4em;  /*padding-right: 0.4em; border-bottom:1px dashed;*/ }
td { text-align: left;  padding-left: 0.4em; padding-right: 0.4em; /*border-right:1px dashed; */}
tr { border: solid; border-width: 1px 0; border-bottom:1px solid blue }


.revision   { /*color: #005599;*/ }
.grammar { list-style-type:none }

</style>

<title>Attributes, annotations, labels</title>

</head>
<body>  

<table class="header"><tbody>
  <tr>
    <th>Document number:&nbsp;&nbsp;</th><th> </th><td class="header">P3661R0</td>
  </tr>
  <tr>
    <th>Date:&nbsp;&nbsp;</th><th> </th><td class="header">2025-03-15</td>
  </tr>
  <tr>
    <th>Audience:&nbsp;&nbsp;</th><th> </th><td class="header">EWG, SG21</td>
  </tr>
  <tr>
    <th>Reply-to:&nbsp;&nbsp;</th><th> </th><td class="header">
        <address>Andrzej Krzemieński &lt;akrzemi1 at gmail dot com&gt;</address>
    </td>
  </tr>
</tbody></table>



<h1>Attributes, annotations, labels</h1>


<p> Attributes turned out to be unsuitable for the role of 
    "small features", "small modifications to bigger features" or <em>annotations</em> from other languages.
    The need for a new kind of non-ignorable annotation pops up time and again in different places.
    Given that the addition of this new kind of entity seems inevitable, 
    we recommend that only one syntax is used for all the cases that need it.
    </p>

<p> This currently concerns three features proposed for C++: </p>

<ul>
<li>annotations for reflection (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3394r1.html" title="Wyatt Childers, Dan Katz, Barry Revzin, Daveed Vandevoorde, “Annotations for Reflection”">[P3394R1]</a>),</li>
<li>the profiles framework (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3589r0.pdf" title="Gabriel Dos Reis, “C++ Profiles: The Framework”">[P3589R0]</a>),</li>
<li>contract labels (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3400r0.pdf" title="Joshua Berne, “Controlling Contract-Assertion Properties”">[P3400R0]</a>).</li>       
</ul>

<p> <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3394r1.html" title="Wyatt Childers, Dan Katz, Barry Revzin, Daveed Vandevoorde, “Annotations for Reflection”">[P3394R1]</a>
    has a model use case for a new kind of annotations: to be able to inject compile-time 
    values to declarations so that they can be read by "metaprograms".
    </p>
    
<pre>[[=timeout(10ms)]]
void test_case("sorting_is_stable")
{
  <em>// ...</em>
}
</pre>

<p> <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3589r0.pdf" title="Gabriel Dos Reis, “C++ Profiles: The Framework”">[P3589R0]</a>
    proposes to use an attribute at a global namespace scope to indicate whether 
    a given profile is enforced in the translation unit. This controls:
    </p>
    
<ul>
  <li>whether some constructs cause a compiler error or not,</li>
  <li>whether some runtime checks are injected (this one is controversial).</li>
</ul>

<p> There are good reasons to use an attribute for this purpose.
    But we also hear objections to this decision. One of them is about <em>ignorability</em>
    of attributes. Some implementations want to ignore all attributes 
    (just ignore any content between <code>[[</code> and <code>]]</code>)
    while still providing the profiles framework.
    </p>
    
<p>Using a non-ignorable annotation would be a way out of this conflict:</p>

<pre>[[=profiles::enforce(std::type)]];
</pre>


<p> It is a bit of a stretch, as there is no metaprogram that would be consuming the embedded data.
    But conceptually one could think of the profile processing as a metaprogram that 
    consumes as data the names of the profiles.
    </p>


<p> Finally, contract assertions. Contract assertions themselves could have been attributes themselves.
    This was objected to, one objection being that we want the platforms that ignore attributes 
    (whether this is legal or not) to still respect the contract assertions. But now 
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3400r0.pdf" title="Joshua Berne, “Controlling Contract-Assertion Properties”">[P3400R0]</a>
    proposes to add <em>labels</em> as means of annotating contract assertions.
    </p>    
  
<pre>void f(int i)
  pre &lt;strict&gt; (i != 0);
</pre>

<p> Here, <code>strict</code> is a compile-time value that controls what instrumentation 
    code is injected. This again looks very close to annotations: some compile-time
    data is passed in to modify the property of a contract assertion:    
    </p>
  
<pre>void f(int i)
  pre [[=strict]] (i != 0);
</pre>

<p> Here again, the annotation syntax would reflect non-ignorability, and the "metaprogram consumes the data"
    interpretation wouldn't be too much of a stretch.
    </p>
  

  
<h2>References</h2>


<ul>

    
<li>[N2761] — Jens Maurer, Michael Wong,
    "Towards support for attributes in C++ (Revision 6)", <br>
    (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2761.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2761.pdf</a>).
    </li>
    <!--
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2761.pdf"
       title="Jens Maurer, Michael Wong, &ldquo;Towards support for attributes in C++ (Revision 6)&rdquo;">[N2761]</a>
    -->
    
<li>[P2552R3] — Timur Doumler, "On the ignorability of standard attributes" <br>
    (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2552r3.pdf">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2552r3.pdf</a>).
    </li>
    <!--
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2552r3.pdf"
       title="Timur Doumler, &ldquo;On the ignorability of standard attributes&rdquo;">[P2552R3]</a>
    -->	  

<li>[P3394R1] — Wyatt Childers, Dan Katz, Barry Revzin, Daveed Vandevoorde,
    "Annotations for Reflection", <br>
    (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3394r1.html">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3394r1.html</a>).
    </li>
    <!--
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3394r1.html"
       title="Wyatt Childers, Dan Katz, Barry Revzin, Daveed Vandevoorde, &ldquo;Annotations for Reflection&rdquo;">[P3394R1]</a>
    -->
    
<li>[P3400R0] — Joshua Berne,
    "Controlling Contract-Assertion Properties", <br>
    (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3400r0.pdf">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3400r0.pdf</a>).
    </li>
    <!--
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3400r0.pdf"
       title="Joshua Berne, &ldquo;Controlling Contract-Assertion Properties&rdquo;">[P3400R0]</a>
    -->
    
    
<li>[P3589R0] — Gabriel Dos Reis,
    "C++ Profiles: The Framework", <br>
    (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3589r0.pdf">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3589r0.pdf</a>).
    </li>
    <!--
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3589r0.pdf"
       title="Gabriel Dos Reis, &ldquo;C++ Profiles: The Framework&rdquo;">[P3589R0]</a>
    -->

</ul>



</body></html>