Skip to content

Commit 9b68d1c

Browse files
committed
P3394R4 Annotations for Reflection
1 parent 178a7f4 commit 9b68d1c

File tree

5 files changed

+212
-12
lines changed

5 files changed

+212
-12
lines changed

source/basic.tex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5590,6 +5590,7 @@
55905590
\item a structured binding\iref{dcl.struct.bind},
55915591
\item a function\iref{dcl.fct},
55925592
\item an enumerator\iref{dcl.enum},
5593+
\item an annotation\iref{dcl.attr.grammar},
55935594
\item a type alias\iref{dcl.typedef},
55945595
\item a type\iref{basic.types},
55955596
\item a class member\iref{class.mem},

source/declarations.tex

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9360,7 +9360,7 @@
93609360

93619361
\pnum
93629362
\indextext{attribute!syntax and semantics}%
9363-
Attributes specify additional information for various source constructs
9363+
Attributes and annotations specify additional information for various source constructs
93649364
such as types, variables, names, contract assertions, blocks, or translation units.
93659365

93669366
\begin{bnf}
@@ -9371,6 +9371,7 @@
93719371
\begin{bnf}
93729372
\nontermdef{attribute-specifier}\br
93739373
\terminal{[} \terminal{[} \opt{attribute-using-prefix} attribute-list \terminal{]} \terminal{]}\br
9374+
\terminal{[} \terminal{[} annotation-list \terminal{]} \terminal{]}\br
93749375
alignment-specifier
93759376
\end{bnf}
93769377

@@ -9393,11 +9394,22 @@
93939394
attribute-list \terminal{,} attribute \terminal{...}
93949395
\end{bnf}
93959396

9397+
\begin{bnf}
9398+
\nontermdef{annotation-list}\br
9399+
annotation \opt{\terminal{...}}\br
9400+
annotation-list \terminal{,} annotation \opt{\terminal{...}}
9401+
\end{bnf}
9402+
93969403
\begin{bnf}
93979404
\nontermdef{attribute}\br
93989405
attribute-token \opt{attribute-argument-clause}
93999406
\end{bnf}
94009407

9408+
\begin{bnf}
9409+
\nontermdef{annotation}\br
9410+
\terminal{=} constant-expression
9411+
\end{bnf}
9412+
94019413
\begin{bnf}
94029414
\nontermdef{attribute-token}\br
94039415
identifier\br
@@ -9470,10 +9482,11 @@
94709482
In an \grammarterm{attribute-list}, an ellipsis may appear only if that
94719483
\grammarterm{attribute}'s specification permits it. An \grammarterm{attribute} followed
94729484
by an ellipsis is a pack expansion\iref{temp.variadic}.
9473-
An \grammarterm{attribute-specifier}
9474-
that contains no \grammarterm{attribute}{s} and no \grammarterm{alignment-specifier}
9475-
has no
9476-
effect. The order in which the \grammarterm{attribute-token}{s} appear in an
9485+
An \grammarterm{attribute-specifier} that contains
9486+
an \grammarterm{attribute-list} with no \grammarterm{attribute}s
9487+
and no \grammarterm{alignment-specifier}
9488+
has no effect.
9489+
The order in which the \grammarterm{attribute-token}{s} appear in an
94779490
\grammarterm{attribute-list} is not significant. If a
94789491
keyword\iref{lex.key}
94799492
or an alternative token\iref{lex.digraph} that satisfies the syntactic requirements
@@ -9484,6 +9497,10 @@
94849497
\grammarterm{attribute-token}. The \grammarterm{attribute-token} determines additional
94859498
requirements on the \grammarterm{attribute-argument-clause} (if any).
94869499

9500+
\pnum
9501+
An \grammarterm{annotation} followed by an ellipsis
9502+
is a pack expansion\iref{temp.variadic}.
9503+
94879504
\pnum
94889505
Each \grammarterm{attribute-specifier-seq} is said to \defn{appertain} to some entity or
94899506
statement, identified by the syntactic context
@@ -10181,5 +10198,58 @@
1018110198
if their respective types are all empty.
1018210199
\end{example}
1018310200

10201+
\rSec2[dcl.attr.annotation]{Annotations}%
10202+
\indextext{attribute!annotations}
10203+
10204+
\pnum
10205+
An annotation may be applied to any declaration of a
10206+
type,
10207+
type alias,
10208+
variable,
10209+
function,
10210+
namespace,
10211+
enumerator,
10212+
\grammarterm{base-specifier}, or
10213+
non-static data member.
10214+
10215+
\pnum
10216+
Let $E$ be the expression
10217+
\tcode{std::meta::reflect_constant(\grammarterm{constant-expression})}.
10218+
%FIXME: weird "shall".
10219+
%I think we would usually say that E simply is a constant expression.
10220+
$E$ shall be a constant expression;
10221+
the result of $E$ is the \defnadj{underlying}{constant} of the annotation.
10222+
10223+
\pnum
10224+
Each \grammarterm{annotation} produces a unique annotation.
10225+
10226+
\pnum
10227+
Substituting into an \grammarterm{annotation}
10228+
is not in the immediate context.
10229+
\begin{example}
10230+
\begin{codeblock}
10231+
[[=1]] void f();
10232+
[[=2, =3, =2]] void g();
10233+
void g [[=4, =2]] ();
10234+
\end{codeblock}
10235+
\tcode{f} has one annotation
10236+
and \tcode{g} has five annotations.
10237+
These can be queried with metafunctions
10238+
such as \tcode{std::\brk{}meta::\brk{}anno\-tations_of}\iref{meta.reflect.annotation}.
10239+
\end{example}
10240+
\begin{example}
10241+
\begin{codeblock}
10242+
template<class T>
10243+
[[=T::type()]] void f(T t);
10244+
10245+
void f(int);
10246+
10247+
void g() {
10248+
f(0); // OK
10249+
f('0'); // error, substituting into the annotation results in an invalid expression
10250+
}
10251+
\end{codeblock}
10252+
\end{example}
10253+
1018410254
\indextext{attribute|)}%
1018510255
\indextext{declaration|)}

source/expressions.tex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7608,6 +7608,7 @@
76087608
\item represent values that are template-argument-equivalent\iref{temp.type},
76097609
\item represent the same object,
76107610
\item represent the same entity,
7611+
\item represent the same annotation\iref{dcl.attr.annotation},
76117612
\item represent the same direct base class relationship, or
76127613
\item represent equal data member descriptions\iref{class.mem.general},
76137614
\end{itemize}

source/meta.tex

Lines changed: 131 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2625,6 +2625,7 @@
26252625

26262626
consteval bool is_bit_field(info r);
26272627
consteval bool is_enumerator(info r);
2628+
consteval bool is_annotation(info r);
26282629

26292630
consteval bool is_const(info r);
26302631
consteval bool is_volatile(info r);
@@ -2912,6 +2913,11 @@
29122913
consteval info variant_alternative(size_t index, info type);
29132914

29142915
consteval strong_ordering type_order(info type_a, info type_b);
2916+
2917+
// \ref{meta.reflection.annotation}, annotation reflection
2918+
consteval vector<info> annotations_of(info item);
2919+
consteval vector<info> annotations_of_with_type(info item, info type);
2920+
29152921
}
29162922
\end{codeblock}
29172923

@@ -3244,6 +3250,7 @@
32443250
\returns
32453251
\tcode{true} if \tcode{r} represents a
32463252
value,
3253+
annotation,
32473254
object,
32483255
variable,
32493256
function whose type does not contain an undeduced placeholder type
@@ -3278,6 +3285,9 @@
32783285
non-static data member, or
32793286
unnamed bit-field,
32803287
then the type of what is represented by \tcode{r}.
3288+
\item
3289+
Otherwise, if \tcode{r} represents an annotation,
3290+
then \tcode{type_of(constant_of(r))}.
32813291
\item
32823292
Otherwise, if \tcode{r} represents
32833293
an enumerator $N$ of an enumeration $E$, then:
@@ -3359,19 +3369,27 @@
33593369

33603370
\begin{itemdescr}
33613371
\pnum
3362-
Let \tcode{\placeholder{R}} be a constant expression of type \tcode{info}
3363-
such that \tcode{\placeholder{R} == r} is \tcode{true}.
3372+
Let $R$ be a constant expression of type \tcode{info}
3373+
such that \tcode{$R$ == r} is \tcode{true}.
3374+
If \tcode{r} represents an annotation,
3375+
then let $C$ be its underlying constant.
33643376

33653377
\pnum
33663378
\constantwhen
3367-
\tcode{[: \placeholder{R} :]} is a valid
3379+
Either \tcode{r} represents an annotation or
3380+
\tcode{[: $R$ :]} is a valid
33683381
\grammarterm{splice-expression}\iref{expr.prim.splice}.
33693382

33703383
\pnum
33713384
\effects
33723385
Equivalent to:
3386+
%FIXME: surely, this is meant to be is_annotation(r)
33733387
\begin{codeblock}
3374-
return reflect_constant([: \placeholder{R} :]);
3388+
if constexpr (is_annotation(R)) {
3389+
return @$C$@;
3390+
} else {
3391+
return reflect_constant([: @$R$@ :]);
3392+
}
33753393
\end{codeblock}
33763394
\begin{example}
33773395
\begin{codeblock}
@@ -3553,14 +3571,16 @@
35533571
\end{itemdescr}
35543572

35553573
\indexlibraryglobal{is_enumerator}%
3574+
\indexlibraryglobal{is_annotation}%
35563575
\begin{itemdecl}
35573576
consteval bool is_enumerator(info r);
3577+
consteval bool is_annotation(info r);
35583578
\end{itemdecl}
35593579

35603580
\begin{itemdescr}
35613581
\pnum
35623582
\returns
3563-
\tcode{true} if \tcode{r} represents an enumerator.
3583+
\tcode{true} if \tcode{r} represents an enumerator or annotation, respectively.
35643584
Otherwise, \tcode{false}.
35653585
\end{itemdescr}
35663586

@@ -5952,6 +5972,112 @@
59525972
represented by \tcode{dealias(t1)} and \tcode{dealias(t2)}, respectively.
59535973
\end{itemdescr}
59545974

5975+
\rSec2[meta.reflection.annotation]{Annotation reflection}
5976+
5977+
\indexlibraryglobal{annotations_of}%
5978+
\begin{itemdecl}
5979+
consteval vector<info> annotations_of(info item);
5980+
\end{itemdecl}
5981+
5982+
\begin{itemdescr}
5983+
\pnum
5984+
\constantwhen
5985+
\tcode{item} represents a
5986+
type,
5987+
type alias,
5988+
variable,
5989+
function,
5990+
namespace,
5991+
enumerator,
5992+
direct base class relationship, or
5993+
non-static data member.
5994+
5995+
%FIXME: it is highly unusual for this subclause to put Let paragraphs after Constant When
5996+
\pnum
5997+
Let $E$ be
5998+
\begin{itemize}
5999+
\item
6000+
the corresponding \grammarterm{base-specifier}
6001+
if \tcode{item} represents a direct base class relationship,
6002+
\item
6003+
otherwise, the entity represented by \tcode{item}.
6004+
\end{itemize}
6005+
6006+
\pnum
6007+
\returns
6008+
A \tcode{vector} containing all of the reflections $R$
6009+
representing each annotation applying to each declaration of $E$ that precedes either
6010+
some point in the evaluation context\iref{expr.const} or
6011+
a point immediately following the \grammarterm{class-specifier}
6012+
of the outermost class for which such a point is in a complete-class context.
6013+
For any two reflections $R_1$ and $R_2$ in the returned \tcode{vector},
6014+
if the annotation represented by $R_1$ precedes the annotation represented by $R_2$,
6015+
then $R_1$ appears before $R_2$.
6016+
If $R_1$ and $R_2$ represent annotations from the same translation unit $T$,
6017+
any element in the returned \tcode{vector} between $R_1$ and $R_2$
6018+
represents an annotation from $T$.
6019+
\begin{note}
6020+
The order in which two annotations appear is otherwise unspecified.
6021+
\end{note}
6022+
\begin{example}
6023+
\begin{codeblock}
6024+
[[=1]] void f();
6025+
[[=2, =3]] void g();
6026+
void g [[=4]] ();
6027+
6028+
static_assert(annotations_of(^^f).size() == 1);
6029+
static_assert(annotations_of(^^g).size() == 3);
6030+
static_assert([: constant_of(annotations_of(^^g)[0]) :] == 2);
6031+
static_assert(extract<int>(annotations_of(^^g)[1]) == 3);
6032+
static_assert(extract<int>(annotations_of(^^g)[2]) == 4);
6033+
6034+
struct Option { bool value; };
6035+
6036+
struct C {
6037+
[[=Option{true}]] int a;
6038+
[[=Option{false}]] int b;
6039+
};
6040+
6041+
static_assert(extract<Option>(annotations_of(^^C::a)[0]).value);
6042+
static_assert(!extract<Option>(annotations_of(^^C::b)[0]).value);
6043+
6044+
template<class T>
6045+
struct [[=42]] D { };
6046+
6047+
constexpr std::meta::info a1 = annotations_of(^^D<int>)[0];
6048+
constexpr std::meta::info a2 = annotations_of(^^D<char>)[0];
6049+
static_assert(a1 != a2);
6050+
static_assert(constant_of(a1) == constant_of(a2));
6051+
6052+
[[=1]] int x, y;
6053+
static_assert(annotations_of(^^x)[0] == annotations_of(^^y)[0]);
6054+
\end{codeblock}
6055+
\end{example}
6056+
\end{itemdescr}
6057+
6058+
\indexlibraryglobal{annotations_of_with_type}%
6059+
\begin{itemdecl}
6060+
consteval vector<info> annotations_of_with_type(info item, info type);
6061+
\end{itemdecl}
6062+
6063+
\begin{itemdescr}
6064+
\pnum
6065+
\constantwhen
6066+
\begin{itemize}
6067+
\item
6068+
\tcode{annotations_of(item)} is a constant expression and
6069+
\item
6070+
\tcode{dealias(type)} represents a type that is complete
6071+
from some point in the evaluation context.
6072+
\end{itemize}
6073+
6074+
\pnum
6075+
\returns
6076+
A \tcode{vector} containing each element \tcode{e} of \tcode{annotations_of(item)}
6077+
where \tcode{remove_const(type_of(e)) == remove_const(type)} is \tcode{true},
6078+
preserving their order.
6079+
\end{itemdescr}
6080+
59556081
\rSec1[ratio]{Compile-time rational arithmetic}
59566082

59576083
\rSec2[ratio.general]{General}

source/templates.tex

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3204,8 +3204,10 @@
32043204
\item In a \grammarterm{template-argument-list}\iref{temp.arg};
32053205
the pattern is a \grammarterm{template-argument}.
32063206

3207-
\item In an \grammarterm{attribute-list}\iref{dcl.attr.grammar}; the pattern is
3208-
an \grammarterm{attribute}.
3207+
\item In an \grammarterm{attribute-list}\iref{dcl.attr.grammar};
3208+
the pattern is an \grammarterm{attribute}.
3209+
In an \grammarterm{annotation-list};
3210+
the pattern is an \grammarterm{annotation}.
32093211

32103212
\item In an \grammarterm{alignment-specifier}\iref{dcl.align}; the pattern is
32113213
the \grammarterm{alignment-specifier} without the ellipsis.

0 commit comments

Comments
 (0)