|
2625 | 2625 |
|
2626 | 2626 | consteval bool is_bit_field(info r); |
2627 | 2627 | consteval bool is_enumerator(info r); |
| 2628 | + consteval bool is_annotation(info r); |
2628 | 2629 |
|
2629 | 2630 | consteval bool is_const(info r); |
2630 | 2631 | consteval bool is_volatile(info r); |
|
2912 | 2913 | consteval info variant_alternative(size_t index, info type); |
2913 | 2914 |
|
2914 | 2915 | 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); |
2915 | 2920 | } |
2916 | 2921 | \end{codeblock} |
2917 | 2922 |
|
|
3243 | 3248 | \returns |
3244 | 3249 | \tcode{true} if \tcode{r} represents a |
3245 | 3250 | value, |
| 3251 | +annotation, |
3246 | 3252 | object, |
3247 | 3253 | variable, |
3248 | 3254 | function whose type does not contain an undeduced placeholder type |
|
3277 | 3283 | non-static data member, or |
3278 | 3284 | unnamed bit-field, |
3279 | 3285 | then the type of what is represented by \tcode{r}. |
| 3286 | +\item |
| 3287 | + Otherwise, if \tcode{r} represents an annotation, |
| 3288 | + then \tcode{type_of(constant_of(r))}. |
3280 | 3289 | \item |
3281 | 3290 | Otherwise, if \tcode{r} represents |
3282 | 3291 | an enumerator $N$ of an enumeration $E$, then: |
|
3358 | 3367 |
|
3359 | 3368 | \begin{itemdescr} |
3360 | 3369 | \pnum |
3361 | | -Let \tcode{\placeholder{R}} be a constant expression of type \tcode{info} |
3362 | | -such that \tcode{\placeholder{R} == r} is \tcode{true}. |
| 3370 | +Let $R$ be a constant expression of type \tcode{info} |
| 3371 | +such that \tcode{$R$ == r} is \tcode{true}. |
| 3372 | +If \tcode{r} represents an annotation, |
| 3373 | +then let $C$ be its underlying constant. |
3363 | 3374 |
|
3364 | 3375 | \pnum |
3365 | 3376 | \constantwhen |
3366 | | -\tcode{[: \placeholder{R} :]} is a valid |
| 3377 | +Either \tcode{r} represents an annotation or |
| 3378 | +\tcode{[: $R$ :]} is a valid |
3367 | 3379 | \grammarterm{splice-expression}\iref{expr.prim.splice}. |
3368 | 3380 |
|
3369 | 3381 | \pnum |
3370 | 3382 | \effects |
3371 | 3383 | Equivalent to: |
3372 | 3384 | \begin{codeblock} |
3373 | | -return reflect_constant([: @\placeholder{R}@ :]); |
| 3385 | +if constexpr (is_annotation(@$R$@)) { |
| 3386 | + return @$C$@; |
| 3387 | +} else { |
| 3388 | + return reflect_constant([: @$R$@ :]); |
| 3389 | +} |
3374 | 3390 | \end{codeblock} |
3375 | 3391 | \begin{example} |
3376 | 3392 | \begin{codeblock} |
|
3552 | 3568 | \end{itemdescr} |
3553 | 3569 |
|
3554 | 3570 | \indexlibraryglobal{is_enumerator}% |
| 3571 | +\indexlibraryglobal{is_annotation}% |
3555 | 3572 | \begin{itemdecl} |
3556 | 3573 | consteval bool is_enumerator(info r); |
| 3574 | +consteval bool is_annotation(info r); |
3557 | 3575 | \end{itemdecl} |
3558 | 3576 |
|
3559 | 3577 | \begin{itemdescr} |
3560 | 3578 | \pnum |
3561 | 3579 | \returns |
3562 | | -\tcode{true} if \tcode{r} represents an enumerator. |
| 3580 | +\tcode{true} if \tcode{r} represents an enumerator or annotation, respectively. |
3563 | 3581 | Otherwise, \tcode{false}. |
3564 | 3582 | \end{itemdescr} |
3565 | 3583 |
|
|
5946 | 5964 | represented by \tcode{dealias(t1)} and \tcode{dealias(t2)}, respectively. |
5947 | 5965 | \end{itemdescr} |
5948 | 5966 |
|
| 5967 | +\rSec2[meta.reflection.annotation]{Annotation reflection} |
| 5968 | + |
| 5969 | +\indexlibraryglobal{annotations_of}% |
| 5970 | +\begin{itemdecl} |
| 5971 | +consteval vector<info> annotations_of(info item); |
| 5972 | +\end{itemdecl} |
| 5973 | + |
| 5974 | +\begin{itemdescr} |
| 5975 | +\pnum |
| 5976 | +\constantwhen |
| 5977 | +\tcode{item} represents a |
| 5978 | +type, |
| 5979 | +type alias, |
| 5980 | +variable, |
| 5981 | +function, |
| 5982 | +namespace, |
| 5983 | +enumerator, |
| 5984 | +direct base class relationship, or |
| 5985 | +non-static data member. |
| 5986 | + |
| 5987 | +%FIXME: it is highly unusual for this subclause to put Let paragraphs after Constant When |
| 5988 | +\pnum |
| 5989 | +Let $E$ be |
| 5990 | +\begin{itemize} |
| 5991 | +\item |
| 5992 | + the corresponding \grammarterm{base-specifier} |
| 5993 | + if \tcode{item} represents a direct base class relationship, |
| 5994 | +\item |
| 5995 | + otherwise, the entity represented by \tcode{item}. |
| 5996 | +\end{itemize} |
| 5997 | + |
| 5998 | +\pnum |
| 5999 | +\returns |
| 6000 | +A \tcode{vector} containing all of the reflections $R$ |
| 6001 | +representing each annotation applying to each declaration of $E$ that precedes either |
| 6002 | +some point in the evaluation context\iref{expr.const} or |
| 6003 | +a point immediately following the \grammarterm{class-specifier} |
| 6004 | +of the outermost class for which such a point is in a complete-class context. |
| 6005 | +For any two reflections $R_1$ and $R_2$ in the returned \tcode{vector}, |
| 6006 | +if the annotation represented by $R_1$ precedes the annotation represented by $R_2$, |
| 6007 | +then $R_1$ appears before $R_2$. |
| 6008 | +If $R_1$ and $R_2$ represent annotations from the same translation unit $T$, |
| 6009 | +any element in the returned \tcode{vector} between $R_1$ and $R_2$ |
| 6010 | +represents an annotation from $T$. |
| 6011 | +\begin{note} |
| 6012 | +The order in which two annotations appear is otherwise unspecified. |
| 6013 | +\end{note} |
| 6014 | +\begin{example} |
| 6015 | +\begin{codeblock} |
| 6016 | +[[=1]] void f(); |
| 6017 | +[[=2, =3]] void g(); |
| 6018 | +void g [[=4]] (); |
| 6019 | + |
| 6020 | +static_assert(annotations_of(^^f).size() == 1); |
| 6021 | +static_assert(annotations_of(^^g).size() == 3); |
| 6022 | +static_assert([: constant_of(annotations_of(^^g)[0]) :] == 2); |
| 6023 | +static_assert(extract<int>(annotations_of(^^g)[1]) == 3); |
| 6024 | +static_assert(extract<int>(annotations_of(^^g)[2]) == 4); |
| 6025 | + |
| 6026 | +struct Option { bool value; }; |
| 6027 | + |
| 6028 | +struct C { |
| 6029 | + [[=Option{true}]] int a; |
| 6030 | + [[=Option{false}]] int b; |
| 6031 | +}; |
| 6032 | + |
| 6033 | +static_assert(extract<Option>(annotations_of(^^C::a)[0]).value); |
| 6034 | +static_assert(!extract<Option>(annotations_of(^^C::b)[0]).value); |
| 6035 | + |
| 6036 | +template<class T> |
| 6037 | + struct [[=42]] D { }; |
| 6038 | + |
| 6039 | +constexpr std::meta::info a1 = annotations_of(^^D<int>)[0]; |
| 6040 | +constexpr std::meta::info a2 = annotations_of(^^D<char>)[0]; |
| 6041 | +static_assert(a1 != a2); |
| 6042 | +static_assert(constant_of(a1) == constant_of(a2)); |
| 6043 | + |
| 6044 | +[[=1]] int x, y; |
| 6045 | +static_assert(annotations_of(^^x)[0] == annotations_of(^^y)[0]); |
| 6046 | +\end{codeblock} |
| 6047 | +\end{example} |
| 6048 | +\end{itemdescr} |
| 6049 | + |
| 6050 | +\indexlibraryglobal{annotations_of_with_type}% |
| 6051 | +\begin{itemdecl} |
| 6052 | +consteval vector<info> annotations_of_with_type(info item, info type); |
| 6053 | +\end{itemdecl} |
| 6054 | + |
| 6055 | +\begin{itemdescr} |
| 6056 | +\pnum |
| 6057 | +\constantwhen |
| 6058 | +\begin{itemize} |
| 6059 | +\item |
| 6060 | + \tcode{annotations_of(item)} is a constant expression and |
| 6061 | +\item |
| 6062 | + \tcode{dealias(type)} represents a type that is complete |
| 6063 | + from some point in the evaluation context. |
| 6064 | +\end{itemize} |
| 6065 | + |
| 6066 | +\pnum |
| 6067 | +\returns |
| 6068 | +A \tcode{vector} containing each element \tcode{e} of \tcode{annotations_of(item)} |
| 6069 | +where |
| 6070 | +\begin{codeblock} |
| 6071 | +remove_const(type_of(e)) == remove_const(type) |
| 6072 | +\end{codeblock} |
| 6073 | +is \tcode{true}, preserving their order. |
| 6074 | +\end{itemdescr} |
| 6075 | + |
5949 | 6076 | \rSec1[ratio]{Compile-time rational arithmetic} |
5950 | 6077 |
|
5951 | 6078 | \rSec2[ratio.general]{General} |
|
0 commit comments