|
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); |
| 2920 | + |
2915 | 2921 | } |
2916 | 2922 | \end{codeblock} |
2917 | 2923 |
|
|
3244 | 3250 | \returns |
3245 | 3251 | \tcode{true} if \tcode{r} represents a |
3246 | 3252 | value, |
| 3253 | +annotation, |
3247 | 3254 | object, |
3248 | 3255 | variable, |
3249 | 3256 | function whose type does not contain an undeduced placeholder type |
|
3278 | 3285 | non-static data member, or |
3279 | 3286 | unnamed bit-field, |
3280 | 3287 | 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))}. |
3281 | 3291 | \item |
3282 | 3292 | Otherwise, if \tcode{r} represents |
3283 | 3293 | an enumerator $N$ of an enumeration $E$, then: |
|
3359 | 3369 |
|
3360 | 3370 | \begin{itemdescr} |
3361 | 3371 | \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. |
3364 | 3376 |
|
3365 | 3377 | \pnum |
3366 | 3378 | \constantwhen |
3367 | | -\tcode{[: \placeholder{R} :]} is a valid |
| 3379 | +Either \tcode{r} represents an annotation or |
| 3380 | +\tcode{[: $R$ :]} is a valid |
3368 | 3381 | \grammarterm{splice-expression}\iref{expr.prim.splice}. |
3369 | 3382 |
|
3370 | 3383 | \pnum |
3371 | 3384 | \effects |
3372 | 3385 | Equivalent to: |
| 3386 | +%FIXME: surely, this is meant to be is_annotation(r) |
3373 | 3387 | \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 | +} |
3375 | 3393 | \end{codeblock} |
3376 | 3394 | \begin{example} |
3377 | 3395 | \begin{codeblock} |
|
3553 | 3571 | \end{itemdescr} |
3554 | 3572 |
|
3555 | 3573 | \indexlibraryglobal{is_enumerator}% |
| 3574 | +\indexlibraryglobal{is_annotation}% |
3556 | 3575 | \begin{itemdecl} |
3557 | 3576 | consteval bool is_enumerator(info r); |
| 3577 | +consteval bool is_annotation(info r); |
3558 | 3578 | \end{itemdecl} |
3559 | 3579 |
|
3560 | 3580 | \begin{itemdescr} |
3561 | 3581 | \pnum |
3562 | 3582 | \returns |
3563 | | -\tcode{true} if \tcode{r} represents an enumerator. |
| 3583 | +\tcode{true} if \tcode{r} represents an enumerator or annotation, respectively. |
3564 | 3584 | Otherwise, \tcode{false}. |
3565 | 3585 | \end{itemdescr} |
3566 | 3586 |
|
|
5952 | 5972 | represented by \tcode{dealias(t1)} and \tcode{dealias(t2)}, respectively. |
5953 | 5973 | \end{itemdescr} |
5954 | 5974 |
|
| 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 | + |
5955 | 6081 | \rSec1[ratio]{Compile-time rational arithmetic} |
5956 | 6082 |
|
5957 | 6083 | \rSec2[ratio.general]{General} |
|
0 commit comments