Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
228 changes: 114 additions & 114 deletions source/meta.tex
Original file line number Diff line number Diff line change
Expand Up @@ -3080,6 +3080,10 @@
consteval size_t alignment_of(info r);
consteval size_t bit_size_of(info r);

// \ref{meta.reflection.annotation}, annotation queries
consteval vector<info> annotations_of(info item);
consteval vector<info> annotations_of_with_type(info item, info type);

// \ref{meta.reflection.extract}, value extraction
template<class T>
consteval T extract(info);
Expand Down Expand Up @@ -3279,10 +3283,6 @@
consteval info variant_alternative(size_t index, info type);

consteval strong_ordering type_order(info type_a, info type_b);

// \ref{meta.reflection.annotation}, annotation reflection
consteval vector<info> annotations_of(info item);
consteval vector<info> annotations_of_with_type(info item, info type);
}
\end{codeblock}

Expand Down Expand Up @@ -5840,6 +5840,116 @@
\end{itemize}
\end{itemdescr}

\rSec2[meta.reflection.annotation]{Annotation queries}

\indexlibraryglobal{annotations_of}%
\begin{itemdecl}
consteval vector<info> annotations_of(info item);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let $E$ be
\begin{itemize}
\item
the corresponding \grammarterm{base-specifier}
if \tcode{item} represents a direct base class relationship,
\item
otherwise, the entity represented by \tcode{item}.
\end{itemize}

\pnum
\returns
A \tcode{vector} containing all of the reflections $R$
representing each annotation applying to each declaration of $E$ that precedes either
some point in the evaluation context\iref{expr.const} or
a point immediately following the \grammarterm{class-specifier}
of the outermost class for which such a point is in a complete-class context.
For any two reflections $R_1$ and $R_2$ in the returned \tcode{vector},
if the annotation represented by $R_1$ precedes the annotation represented by $R_2$,
then $R_1$ appears before $R_2$.
If $R_1$ and $R_2$ represent annotations from the same translation unit $T$,
any element in the returned \tcode{vector} between $R_1$ and $R_2$
represents an annotation from $T$.
\begin{note}
The order in which two annotations appear is otherwise unspecified.
\end{note}
\begin{example}
\begin{codeblock}
[[=1]] void f();
[[=2, =3]] void g();
void g [[=4]] ();

static_assert(annotations_of(^^f).size() == 1);
static_assert(annotations_of(^^g).size() == 3);
static_assert([: constant_of(annotations_of(^^g)[0]) :] == 2);
static_assert(extract<int>(annotations_of(^^g)[1]) == 3);
static_assert(extract<int>(annotations_of(^^g)[2]) == 4);

struct Option { bool value; };

struct C {
[[=Option{true}]] int a;
[[=Option{false}]] int b;
};

static_assert(extract<Option>(annotations_of(^^C::a)[0]).value);
static_assert(!extract<Option>(annotations_of(^^C::b)[0]).value);

template<class T>
struct [[=42]] D { };

constexpr std::meta::info a1 = annotations_of(^^D<int>)[0];
constexpr std::meta::info a2 = annotations_of(^^D<char>)[0];
static_assert(a1 != a2);
static_assert(constant_of(a1) == constant_of(a2));

[[=1]] int x, y;
static_assert(annotations_of(^^x)[0] == annotations_of(^^y)[0]);
\end{codeblock}
\end{example}

\pnum
\throws
\tcode{meta::exception} unless
\tcode{item} represents a
type,
type alias,
variable,
function,
namespace,
enumerator,
direct base class relationship, or
non-static data member.
\end{itemdescr}

\indexlibraryglobal{annotations_of_with_type}%
\begin{itemdecl}
consteval vector<info> annotations_of_with_type(info item, info type);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{vector} containing each element \tcode{e} of \tcode{annotations_of(item)}
where
\begin{codeblock}
remove_const(type_of(e)) == remove_const(type)
\end{codeblock}
is \tcode{true}, preserving their order.

\pnum
\throws
\tcode{meta::exception} unless
\begin{itemize}
\item
\tcode{annotations_of(item)} is a constant expression and
\item
\tcode{dealias(type)} represents a type that is complete
from some point in the evaluation context.
\end{itemize}
\end{itemdescr}

\rSec2[meta.reflection.extract]{Value extraction}

\pnum
Expand Down Expand Up @@ -6925,116 +7035,6 @@
represented by \tcode{dealias(t1)} and \tcode{dealias(t2)}, respectively.
\end{itemdescr}

\rSec2[meta.reflection.annotation]{Annotation reflection}

\indexlibraryglobal{annotations_of}%
\begin{itemdecl}
consteval vector<info> annotations_of(info item);
\end{itemdecl}

\begin{itemdescr}
\pnum
Let $E$ be
\begin{itemize}
\item
the corresponding \grammarterm{base-specifier}
if \tcode{item} represents a direct base class relationship,
\item
otherwise, the entity represented by \tcode{item}.
\end{itemize}

\pnum
\returns
A \tcode{vector} containing all of the reflections $R$
representing each annotation applying to each declaration of $E$ that precedes either
some point in the evaluation context\iref{expr.const} or
a point immediately following the \grammarterm{class-specifier}
of the outermost class for which such a point is in a complete-class context.
For any two reflections $R_1$ and $R_2$ in the returned \tcode{vector},
if the annotation represented by $R_1$ precedes the annotation represented by $R_2$,
then $R_1$ appears before $R_2$.
If $R_1$ and $R_2$ represent annotations from the same translation unit $T$,
any element in the returned \tcode{vector} between $R_1$ and $R_2$
represents an annotation from $T$.
\begin{note}
The order in which two annotations appear is otherwise unspecified.
\end{note}
\begin{example}
\begin{codeblock}
[[=1]] void f();
[[=2, =3]] void g();
void g [[=4]] ();

static_assert(annotations_of(^^f).size() == 1);
static_assert(annotations_of(^^g).size() == 3);
static_assert([: constant_of(annotations_of(^^g)[0]) :] == 2);
static_assert(extract<int>(annotations_of(^^g)[1]) == 3);
static_assert(extract<int>(annotations_of(^^g)[2]) == 4);

struct Option { bool value; };

struct C {
[[=Option{true}]] int a;
[[=Option{false}]] int b;
};

static_assert(extract<Option>(annotations_of(^^C::a)[0]).value);
static_assert(!extract<Option>(annotations_of(^^C::b)[0]).value);

template<class T>
struct [[=42]] D { };

constexpr std::meta::info a1 = annotations_of(^^D<int>)[0];
constexpr std::meta::info a2 = annotations_of(^^D<char>)[0];
static_assert(a1 != a2);
static_assert(constant_of(a1) == constant_of(a2));

[[=1]] int x, y;
static_assert(annotations_of(^^x)[0] == annotations_of(^^y)[0]);
\end{codeblock}
\end{example}

\pnum
\throws
\tcode{meta::exception} unless
\tcode{item} represents a
type,
type alias,
variable,
function,
namespace,
enumerator,
direct base class relationship, or
non-static data member.
\end{itemdescr}

\indexlibraryglobal{annotations_of_with_type}%
\begin{itemdecl}
consteval vector<info> annotations_of_with_type(info item, info type);
\end{itemdecl}

\begin{itemdescr}
\pnum
\returns
A \tcode{vector} containing each element \tcode{e} of \tcode{annotations_of(item)}
where
\begin{codeblock}
remove_const(type_of(e)) == remove_const(type)
\end{codeblock}
is \tcode{true}, preserving their order.

\pnum
\throws
\tcode{meta::exception} unless
\begin{itemize}
\item
\tcode{annotations_of(item)} is a constant expression and
\item
\tcode{dealias(type)} represents a type that is complete
from some point in the evaluation context.
\end{itemize}
\end{itemdescr}

\rSec1[ratio]{Compile-time rational arithmetic}

\rSec2[ratio.general]{General}
Expand Down