Skip to content

P3074R7 trivial unions (was std::uninitialized<T>) #7680

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
Feb 24, 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
102 changes: 61 additions & 41 deletions source/classes.tex
Original file line number Diff line number Diff line change
Expand Up @@ -1220,59 +1220,64 @@
\item any non-static data member with no default member initializer\iref{class.mem} is
of reference type,

\item any non-variant non-static data member of const-qualified type
\item \tcode{X} is a non-union class and
any non-variant non-static data member of const-qualified type
(or possibly multidimensional array thereof)
with no \grammarterm{brace-or-equal-initializer}
is not const-default-constructible\iref{dcl.init},

\item \tcode{X} is a union and all of its variant members are of const-qualified
type (or possibly multidimensional array thereof),

\item \tcode{X} is a non-union class and all members of any anonymous union member are
of const-qualified type (or possibly multidimensional array thereof),

\item any potentially constructed subobject, except for a non-static data member
with a \grammarterm{brace-or-equal-initializer}
or a variant member of a union where another non-static data member
has a \grammarterm{brace-or-equal-initializer},
\item any non-variant potentially constructed subobject, except for a non-static data member
with a \grammarterm{brace-or-equal-initializer},
has class type \tcode{M} (or possibly multidimensional array thereof)
and overload resolution\iref{over.match}
as applied to find \tcode{M}'s corresponding constructor
either does not result in a usable candidate\iref{over.match.general}
or, in the case of a variant member, selects a non-trivial function, or
does not result in a usable candidate\iref{over.match.general}, or

\item any potentially constructed subobject has
class type \tcode{M} (or possibly multidimensional array thereof) and
\item any potentially constructed subobject $S$ has
class type \tcode{M} (or possibly multidimensional array thereof),
\tcode{M} has
a destructor that is deleted or inaccessible from the defaulted default
constructor.
constructor, and
either $S$ is non-variant or $S$ has a default member initializer.
\end{itemize}

\pnum
A default constructor is
A default constructor for a class \tcode{X} is
\defnx{trivial}{constructor!default!trivial}
if it is not user-provided and if
\begin{itemize}
\item
its class has no virtual functions\iref{class.virtual} and no virtual base
\tcode{X} has no virtual functions\iref{class.virtual} and no virtual base
classes\iref{class.mi}, and

\item no non-static data member of its class has
\item no non-static data member of \tcode{X} has
a default member initializer\iref{class.mem}, and

\item
all the direct base classes of its class have trivial default constructors, and
all the direct base classes of \tcode{X} have trivial default constructors, and

\item
for all the non-static data members of its class that are of class
either \tcode{X} is a union or
for all the non-variant non-static data members of \tcode{X} that are of class
type (or array thereof), each such class has a trivial default constructor.
\end{itemize}

Otherwise, the default constructor is
\defnx{non-trivial}{constructor!default!non-trivial}.

\pnum
An implicitly-defined\iref{dcl.fct.def.default} default constructor performs the set of
If a default constructor of a union-like class \tcode{X} is trivial,
then for each union \tcode{U}
that is either \tcode{X} or an anonymous union member of \tcode{X},
if the first variant member, if any, of \tcode{U}
has implicit-lifetime type\iref{basic.types.general},
the default constructor of \tcode{X} begins the lifetime of that member
if it is not the active member of its union.
\begin{note}
It is already the active member if \tcode{U} was value-initialized.
\end{note}
Otherwise,
an implicitly-defined\iref{dcl.fct.def.default} default constructor performs the set of
initializations of the class that would be performed by a user-written default
constructor for that class with no
\grammarterm{ctor-initializer}\iref{class.base.init} and an empty
Expand Down Expand Up @@ -2022,25 +2027,40 @@
A defaulted destructor for a class
\tcode{X} is defined as deleted if
\begin{itemize}
\item any potentially constructed subobject has class type
\tcode{M} (or possibly multidimensional array thereof) and
\item \tcode{X} is a non-union class and
any non-variant potentially constructed subobject has class type
\tcode{M} (or possibly multidimensional array thereof) where
\tcode{M} has a destructor that is deleted or
is inaccessible from the defaulted destructor or,
in the case of a variant member, is non-trivial,
is inaccessible from the defaulted destructor,

\item or, for a virtual destructor, lookup of the non-array deallocation
\item
\tcode{X} is a union and
\begin{itemize}
\item
overload resolution to select a constructor to
default-initialize an object of type \tcode{X} either fails or
selects a constructor that is either deleted or not trivial, or
\item
\tcode{X} has a variant member \tcode{V} of
class type \tcode{M} (or possibly multi-dimensional array thereof)
where \tcode{V} has a default member initializer and
\tcode{M} has a destructor that is non-trivial, or,
\end{itemize}

\item for a virtual destructor, lookup of the non-array deallocation
function results in an ambiguity or in a function that is deleted or
inaccessible from the defaulted destructor.
\end{itemize}

\pnum
A destructor is trivial if it is not user-provided and if
A destructor for a class \tcode{X} is trivial if it is not user-provided and if
\begin{itemize}
\item the destructor is not virtual,

\item all of the direct base classes of its class have trivial destructors, and
\item all of the direct base classes of \tcode{X} have trivial destructors, and

\item for all of the non-static data members of its class that are of class
\item either \tcode{X} is a union or
for all of the non-variant non-static data members of \tcode{X} that are of class
type (or array thereof), each such class has a trivial destructor.
\end{itemize}

Expand Down Expand Up @@ -3054,12 +3074,12 @@
If a union contains a non-static data member of
reference type, the program is ill-formed.
\begin{note}
Absent default member initializers\iref{class.mem},
if any non-static data member of a union has a non-trivial
default constructor\iref{class.default.ctor},
copy constructor, move constructor\iref{class.copy.ctor},
copy assignment operator, move assignment operator\iref{class.copy.assign},
or destructor\iref{class.dtor}, the corresponding member function
If any non-static data member of a union has a non-trivial
copy constructor,
move constructor\iref{class.copy.ctor},
copy assignment operator, or
move assignment operator\iref{class.copy.assign},
the corresponding member function
of the union must be user-provided or it will
be implicitly deleted\iref{dcl.fct.def.delete} for the union.
\begin{example}
Expand All @@ -3072,11 +3092,11 @@
};
\end{codeblock}
Since \tcode{std::string}\iref{string.classes} declares non-trivial versions of all of the special
member functions, \tcode{U} will have an implicitly deleted default constructor,
copy/move constructor,
copy/move assignment operator, and destructor.
To use \tcode{U}, some or all of these member functions
must be user-provided.
member functions, \tcode{U} will have an implicitly deleted
copy/move constructor and copy/move assignment operator.
The default constructor and destructor of \tcode{U} are both trivial
even though \tcode{std::string} has
a non-trivial default constructor and a non-trivial destructor.
\end{example}
\end{note}

Expand Down
7 changes: 0 additions & 7 deletions source/containers.tex
Original file line number Diff line number Diff line change
Expand Up @@ -9534,13 +9534,6 @@
\tcode{inplace_vector<T, N>::const_iterator}
meet the constexpr iterator requirements.

\pnum
For any $\tcode{N} > 0$,
if \tcode{T} is not trivially copyable or
\tcode{is_trivially_default_constructible_v<T>} is \tcode{false},
then no \tcode{inplace_vector<T, N>} member functions
are usable in constant expressions.

\pnum
Any member function of \tcode{inplace_vector<T, N>} that
would cause the size to exceed \tcode{N}
Expand Down
1 change: 1 addition & 0 deletions source/preprocessor.tex
Original file line number Diff line number Diff line change
Expand Up @@ -1908,6 +1908,7 @@
\defnxname{cpp_structured_bindings} & \tcode{202411L} \\ \rowsep
\defnxname{cpp_template_template_args} & \tcode{201611L} \\ \rowsep
\defnxname{cpp_threadsafe_static_init} & \tcode{200806L} \\ \rowsep
\defnxname{cpp_trivial_union} & \tcode{202502L} \\ \rowsep
\defnxname{cpp_unicode_characters} & \tcode{200704L} \\ \rowsep
\defnxname{cpp_unicode_literals} & \tcode{200710L} \\ \rowsep
\defnxname{cpp_user_defined_literals} & \tcode{200809L} \\ \rowsep
Expand Down
1 change: 1 addition & 0 deletions source/support.tex
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,7 @@
#define @\defnlibxname{cpp_lib_constexpr_dynamic_alloc}@ 201907L // also in \libheader{memory}
#define @\defnlibxname{cpp_lib_constexpr_exceptions}@ 202411L // also in \libheader{exception}
#define @\defnlibxname{cpp_lib_constexpr_functional}@ 201907L // freestanding, also in \libheader{functional}
#define @\defnlibxname{cpp_lib_constexpr_inplace_vector}@ 202502L // also in \libheader{inplace_vector}
#define @\defnlibxname{cpp_lib_constexpr_iterator}@ 201811L // freestanding, also in \libheader{iterator}
#define @\defnlibxname{cpp_lib_constexpr_memory}@ 202202L // freestanding, also in \libheader{memory}
#define @\defnlibxname{cpp_lib_constexpr_new}@ 202406L // freestanding, also in \libheader{new}
Expand Down