From 0eb46ae7a6c5776505a63f42ca7dee84e7a8e20c Mon Sep 17 00:00:00 2001 From: Eisenwave Date: Thu, 10 Jul 2025 09:38:58 +0200 Subject: [PATCH] P3293R3 Splicing a base class subobject --- source/expressions.tex | 41 +++++++++++++++++++++++++++++++++++++++-- source/meta.tex | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/source/expressions.tex b/source/expressions.tex index d3670fa297..7d874d73dd 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -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 @@ -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 @@ -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} diff --git a/source/meta.tex b/source/meta.tex index fe90847f6d..7495f5fbfe 100644 --- a/source/meta.tex +++ b/source/meta.tex @@ -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 members_of(info r, access_context ctx); consteval vector bases_of(info type, access_context ctx); consteval vector static_data_members_of(info type, access_context ctx); consteval vector nonstatic_data_members_of(info type, access_context ctx); + consteval vector subobjects_of(info type, access_context ctx); consteval vector enumerators_of(info type_enum); // \ref{meta.reflection.layout}, reflection layout queries @@ -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}% @@ -4795,6 +4811,24 @@ preserving their order. \end{itemdescr} +\indexlibraryglobal{subobjects_of}% +\begin{itemdecl} +consteval vector 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 enumerators_of(info type_enum);