Skip to content

Commit b93b8a2

Browse files
committed
Merge 2026-03 CWG Motion 9
P3726R2 Adjustments to Union Lifetime Rules
2 parents 7db0b92 + b621f1a commit b93b8a2

6 files changed

Lines changed: 83 additions & 16 deletions

File tree

source/basic.tex

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3694,23 +3694,71 @@
36943694
the address of an unspecified byte of storage
36953695
occupied by the complete object of that subobject.
36963696

3697+
\pnum
3698+
A \defnadj{union elemental}{subobject}
3699+
\indextext{union!elemental subobject|see{subobject, union elemental}}
3700+
is a direct member of a union or
3701+
an element of an array that is a union elemental subobject.
3702+
An \defnx{inactive union elemental subobject}{subobject!union elemental!inactive}
3703+
\indextext{inactive union elemental subobject|see{subobject, union elemental, inactive}}
3704+
\indextext{union!inactive elemental subobject|see{subobject, union elemental, inactive}}
3705+
is a union elemental subobject that is not within its lifetime.
3706+
36973707
\pnum
36983708
The \defnx{constituent values}{constituent value} of an object $o$ are
36993709
\begin{itemize}
37003710
\item
37013711
if $o$ has scalar type, the value of $o$;
37023712
\item
37033713
otherwise, the constituent values of any direct subobjects of $o$
3704-
other than inactive union members.
3714+
other than inactive union elemental subobjects.
37053715
\end{itemize}
37063716
The \defnx{constituent references}{constituent reference} of an object $o$ are
37073717
\begin{itemize}
37083718
\item
37093719
any direct members of $o$ that have reference type, and
37103720
\item
37113721
the constituent references of any direct subobjects of $o$
3712-
other than inactive union members.
3722+
other than inactive union elemental subobjects.
37133723
\end{itemize}
3724+
\begin{example}
3725+
\begin{codeblock}
3726+
struct A {
3727+
struct X {
3728+
int i;
3729+
int j;
3730+
};
3731+
3732+
struct Y {
3733+
X x1;
3734+
X x2;
3735+
};
3736+
3737+
union {
3738+
int i;
3739+
int arr[4];
3740+
Y y;
3741+
};
3742+
};
3743+
3744+
constexpr A v1; // OK, no constituent values
3745+
constexpr A v2{.i=1}; // OK, the constituent values are \tcode{\{v2.i\}}
3746+
constexpr A v3 = []{
3747+
A a;
3748+
std::start_lifetime(a.arr); // OK, arr is now the active element of the union
3749+
new (&a.arr[1]) int(1);
3750+
a.arr[2] = 2;
3751+
return a;
3752+
}(); // OK, the constituent values are \tcode{\{v3.arr[1], v3.arr[2]\}}
3753+
constexpr A v4 = []{
3754+
A a;
3755+
a.y.x1.i = 1;
3756+
a.y.x2.j = 2;
3757+
return a;
3758+
}(); // error: the constituent values include \tcode{v4.y.x1.j} and \tcode{v4.y.x2.i}
3759+
// which have erroneous value
3760+
\end{codeblock}
3761+
\end{example}
37143762

37153763
\pnum
37163764
Some operations are described as

source/classes.tex

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,18 +1337,7 @@
13371337
\defnx{non-trivial}{constructor!default!non-trivial}.
13381338

13391339
\pnum
1340-
If a default constructor of a union-like class \tcode{X} is trivial,
1341-
then for each union \tcode{U}
1342-
that is either \tcode{X} or an anonymous union member of \tcode{X},
1343-
if the first variant member, if any, of \tcode{U}
1344-
has implicit-lifetime type\iref{basic.types.general},
1345-
the default constructor of \tcode{X} begins the lifetime of that member
1346-
if it is not the active member of its union.
1347-
\begin{note}
1348-
It is already the active member if \tcode{U} was value-initialized.
1349-
\end{note}
1350-
Otherwise,
1351-
an implicitly-defined\iref{dcl.fct.def.default} default constructor performs the set of
1340+
An implicitly-defined\iref{dcl.fct.def.default} default constructor performs the set of
13521341
initializations of the class that would be performed by a user-written default
13531342
constructor for that class with no
13541343
\grammarterm{ctor-initializer}\iref{class.base.init} and an empty

source/memory.tex

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@
8888
bool is_sufficiently_aligned(T* ptr); // freestanding
8989

9090
// \ref{obj.lifetime}, explicit lifetime management
91+
template<class T>
92+
constexpr void start_lifetime(T& r) noexcept; // freestanding
9193
template<class T>
9294
T* start_lifetime_as(void* p) noexcept; // freestanding
9395
template<class T>
@@ -1036,6 +1038,31 @@
10361038

10371039
\rSec2[obj.lifetime]{Explicit lifetime management}
10381040

1041+
\indexlibraryglobal{start_lifetime}%
1042+
\begin{itemdecl}
1043+
template<class T>
1044+
constexpr void start_lifetime(T& r) noexcept;
1045+
\end{itemdecl}
1046+
1047+
\begin{itemdescr}
1048+
\pnum
1049+
\mandates
1050+
\tcode{T} is a complete type and
1051+
an implicit-lifetime\iref{basic.types} aggregate\iref{dcl.init.aggr}.
1052+
1053+
\pnum
1054+
\effects
1055+
If the object referenced by \tcode{r}
1056+
is already within its lifetime\iref{basic.life},
1057+
no effects.
1058+
Otherwise, begins the lifetime of the object referenced by \tcode{r}.
1059+
\begin{note}
1060+
No initialization is performed and no subobject has its lifetime started.
1061+
If \tcode{r} denotes a member of a union $U$,
1062+
it becomes the active member of $U$\iref{class.union}.
1063+
\end{note}
1064+
\end{itemdescr}
1065+
10391066
\indexlibraryglobal{start_lifetime_as}%
10401067
\begin{itemdecl}
10411068
template<class T>

source/preprocessor.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2451,7 +2451,7 @@
24512451
\defnxname{cpp_template_parameters} & \tcode{202502L} \\ \rowsep
24522452
\defnxname{cpp_template_template_args} & \tcode{201611L} \\ \rowsep
24532453
\defnxname{cpp_threadsafe_static_init} & \tcode{200806L} \\ \rowsep
2454-
\defnxname{cpp_trivial_union} & \tcode{202502L} \\ \rowsep
2454+
\defnxname{cpp_trivial_union} & \tcode{202603L} \\ \rowsep
24552455
\defnxname{cpp_unicode_characters} & \tcode{200704L} \\ \rowsep
24562456
\defnxname{cpp_unicode_literals} & \tcode{200710L} \\ \rowsep
24572457
\defnxname{cpp_user_defined_literals} & \tcode{200809L} \\ \rowsep

source/support.tex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,7 @@
844844
#define @\defnlibxname{cpp_lib_ssize}@ 201902L // freestanding, also in \libheader{iterator}
845845
#define @\defnlibxname{cpp_lib_sstream_from_string_view}@ 202306L // also in \libheader{sstream}
846846
#define @\defnlibxname{cpp_lib_stacktrace}@ 202011L // also in \libheader{stacktrace}
847+
#define @\defnlibxname{cpp_lib_start_lifetime}@ 202603L // freestanding, also in \libheader{memory}
847848
#define @\defnlibxname{cpp_lib_start_lifetime_as}@ 202207L // freestanding, also in \libheader{memory}
848849
#define @\defnlibxname{cpp_lib_starts_ends_with}@ 201711L // also in \libheader{string}, \libheader{string_view}
849850
#define @\defnlibxname{cpp_lib_stdatomic_h}@ 202011L // also in \libheader{stdatomic.h}

source/templates.tex

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2574,7 +2574,9 @@
25742574
they are of reference type and they refer to the same object or function, or
25752575

25762576
\item
2577-
they are of array type and their corresponding elements are template-argument-equivalent,
2577+
they are of array type and their corresponding elements are either
2578+
both within their lifetimes and template-argument-equivalent or
2579+
both not within their lifetimes,
25782580
\begin{footnote}
25792581
An array as a \grammarterm{template-parameter} decays to a pointer.
25802582
\end{footnote}

0 commit comments

Comments
 (0)