Skip to content

P3293R3 Splicing a base class subobject #8042

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 14, 2025
Merged
Show file tree
Hide file tree
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
41 changes: 39 additions & 2 deletions source/expressions.tex
Original file line number Diff line number Diff line change
Expand Up @@ -4219,7 +4219,10 @@

\pnum
If \tcode{E2} is a \grammarterm{splice-expression},
then \tcode{E2} shall designate a member of the type of \tcode{E1}.
then let \tcode{T1} be the type of \tcode{E1}.
\tcode{E2} shall designate either
a member of the \tcode{T1} or
a direct base class relationship $(\tcode{T1}, \tcode{B})$.

\pnum
If \tcode{E2} designates a bit-field, \tcode{E1.E2} is a bit-field. The
Expand Down Expand Up @@ -4249,7 +4252,7 @@
\item Otherwise, if \tcode{E2} designates a non-static data member and the type of
\tcode{E1} is ``\cvqual{cq1 vq1} \tcode{X}'', and the type of \tcode{E2}
is ``\cvqual{cq2 vq2} \tcode{T}'', the expression designates the corresponding
member subobject of the object designated by the first expression. If \tcode{E1}
member subobject of the object designated by \tcode{E1}. If \tcode{E1}
is an lvalue, then \tcode{E1.E2} is an lvalue;
otherwise \tcode{E1.E2} is an xvalue.
Let the notation \cvqual{vq12} stand for the ``union'' of
Expand Down Expand Up @@ -4292,6 +4295,40 @@
is \tcode{T}, the expression \tcode{E1.E2} is a prvalue of type \tcode{T}
whose value is the value of the enumerator.

\item If \tcode{E2} designates a direct base class relationship $(D, B)$
and the type of \tcode{E1} is \cv{} \tcode{T},
the expression designates the direct base class subobject of type $B$
of the object designated by \tcode{E1}.
If \tcode{E1} is an lvalue,
then \tcode{E1.E2} is an lvalue;
otherwise, \tcode{E1.E2} is an xvalue.
The type of \tcode{E1.E2} is ``\cv{} \tcode{$B$}''.
\begin{note}
This can only occur in an expression of the form \tcode{e1.[:e2:]}.
\end{note}
\begin{example}
\begin{codeblock}
struct B {
int b;
};
struct C : B {
int get() const { return b; }
};
struct D : B, C { };

constexpr int f() {
D d = {1, {}};

// \tcode{b} unambiguously refers to the direct base class of type \tcode{B},
// not the indirect base class of type \tcode{B}
B& b = d.[: std::meta::bases_of(^^D, std::meta::access_context::current())[0] :];
b.b += 10;
return 10 * b.b + d.get();
}
static_assert(f() == 110);
\end{codeblock}
\end{example}

\item Otherwise, the program is ill-formed.
\end{itemize}

Expand Down
34 changes: 34 additions & 0 deletions source/meta.tex
Original file line number Diff line number Diff line change
Expand Up @@ -2706,12 +2706,14 @@
consteval bool is_accessible(info r, access_context ctx);
consteval bool has_inaccessible_nonstatic_data_members(info r, access_context ctx);
consteval bool has_inaccessible_bases(info r, access_context ctx);
consteval bool has_inaccessible_subobjects(info r, access_context ctx);

// \ref{meta.reflection.member.queries}, reflection member queries
consteval vector<info> members_of(info r, access_context ctx);
consteval vector<info> bases_of(info type, access_context ctx);
consteval vector<info> static_data_members_of(info type, access_context ctx);
consteval vector<info> nonstatic_data_members_of(info type, access_context ctx);
consteval vector<info> subobjects_of(info type, access_context ctx);
consteval vector<info> enumerators_of(info type_enum);

// \ref{meta.reflection.layout}, reflection layout queries
Expand Down Expand Up @@ -4589,6 +4591,20 @@
Otherwise, \tcode{false}.
\end{itemdescr}

\indexlibraryglobal{has_inaccessible_subobjects}%
\begin{itemdecl}
consteval bool has_inaccessible_subobjects(info r, access_context ctx);
\end{itemdecl}

\begin{itemdescr}
\pnum
\effects
Equivalent to:
\begin{codeblock}
return has_inaccessible_bases(r, ctx) || has_inaccessible_nonstatic_data_members(r, ctx);
\end{codeblock}
\end{itemdescr}

\rSec2[meta.reflection.member.queries]{Reflection member queries}

\indexlibraryglobal{members_of}%
Expand Down Expand Up @@ -4795,6 +4811,24 @@
preserving their order.
\end{itemdescr}

\indexlibraryglobal{subobjects_of}%
\begin{itemdecl}
consteval vector<info> subobjects_of(info type, access_context ctx);
\end{itemdecl}

\begin{itemdescr}
\pnum
\constantwhen
\tcode{dealias(type)} represents a class type
that is complete from some point in the evaluation context.

\pnum
\returns
A \tcode{vector} containing each element of \tcode{bases_of(type, ctx)}
followed by each element of \tcode{non\-static_data_mem\-bers_of(\brk{}type,\brk{} ctx)},
preserving their order.
\end{itemdescr}

\indexlibraryglobal{enumerators_of}%
\begin{itemdecl}
consteval vector<info> enumerators_of(info type_enum);
Expand Down