diff --git a/source/basic.tex b/source/basic.tex index 1f052f1bc7..5114348990 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -3596,9 +3596,17 @@ \pnum An object is a \defnadj{potentially non-unique}{object} if it is -a string literal object\iref{lex.string}, -the backing array of an initializer list\iref{dcl.init.ref}, or -a subobject thereof. +\begin{itemize} +\item + a string literal object\iref{lex.string}, +\item + the backing array of an initializer list\iref{dcl.init.ref}, or +\item + the object introduced by a call to \tcode{std::meta::reflect_constant_array} + or \tcode{std::meta::\brk{}reflect_con\-stant_string}\iref{meta.reflection.array}, or +\item + a subobject thereof. +\end{itemize} \pnum \indextext{most derived object!bit-field}% diff --git a/source/meta.tex b/source/meta.tex index 7495f5fbfe..5bbf10c670 100644 --- a/source/meta.tex +++ b/source/meta.tex @@ -2579,6 +2579,23 @@ \begin{codeblock} #include // see \ref{initializer.list.syn} +namespace std { + // \ref{meta.string.literal}, checking string literals + consteval bool is_string_literal(const char* p); + consteval bool is_string_literal(const wchar_t* p); + consteval bool is_string_literal(const char8_t* p); + consteval bool is_string_literal(const char16_t* p); + consteval bool is_string_literal(const char32_t* p); + + // \ref{meta.define.static}, promoting to static storage strings + template + consteval const ranges::range_value_t* define_static_string(R&& r); + template + consteval span> define_static_array(R&& r); + template + consteval const remove_cvref_t* define_static_object(T&& r); +} + namespace std::meta { using info = decltype(^^::); @@ -2744,6 +2761,13 @@ template consteval info reflect_function(T& fn); + // \ref{meta.reflection.array}, promoting to static storage arrays + template + consteval info reflect_constant_string(R&& r); + + template + consteval info reflect_constant_array(R&& r); + // \ref{meta.reflection.define.aggregate}, class definition generation struct data_member_options; consteval info data_member_spec(info type, data_member_options options); @@ -2974,6 +2998,102 @@ \end{codeblock} \end{example} +\rSec2[meta.string.literal]{Checking string literals} + +\indexlibraryglobal{is_string_literal}% +\begin{itemdecl} +consteval bool is_string_literal(const char* p); +consteval bool is_string_literal(const wchar_t* p); +consteval bool is_string_literal(const char8_t* p); +consteval bool is_string_literal(const char16_t* p); +consteval bool is_string_literal(const char32_t* p); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item + If \tcode{p} points to an unspecified object\iref{expr.const}, + \tcode{false}. +\item + Otherwise, if \tcode{p} points to a subobject + of a string literal object\iref{lex.string}, + \tcode{true}. +\item + Otherwise, \tcode{false}. +\end{itemize} +\end{itemdescr} + +\rSec2[meta.define.static]{Promoting to static storage strings} + +\pnum +The functions in this subclause promote compile-time storage into static storage. + +\indexlibraryglobal{define_static_string}% +\begin{itemdecl} +template + consteval const ranges::range_value_t* define_static_string(R&& r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return extract*>(meta::reflect_constant_string(r)); +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{define_static_array}% +\begin{itemdecl} +template + consteval span> define_static_array(R&& r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +using T = ranges::range_value_t; +meta::info array = meta::reflect_constant_array(r); +if (is_array_type(type_of(array))) { + return span(extract(array), extent(type_of(array))); +} else { + return span(); +} +\end{codeblock} +\end{itemdescr} + +\indexlibraryglobal{define_static_object}% +\begin{itemdecl} +template + consteval const remove_cvref_t* define_static_object(T&& t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +using U = remove_cvref_t; +if constexpr (is_class_type(^^U)) { + return addressof(extract(meta::reflect_constant(std::forward(t)))); +} else { + return define_static_array(span(addressof(t), 1)).data(); +} +\end{codeblock} + +\pnum +\begin{note} +For class types, +\tcode{define_static_object} provides +the address of the template parameter object\iref{temp.param} +that is template-argument equivalent to \tcode{t}. +\end{note} +\end{itemdescr} + \rSec2[meta.reflection.operators]{Operator representations} \begin{itemdecl} @@ -5368,6 +5488,102 @@ A reflection of the function designated by \tcode{fn}. \end{itemdescr} +\rSec2[meta.reflection.array]{Promoting to static storage arrays} + +\pnum +The functions in this subclause promote compile-time storage into static storage. + +\indexlibraryglobal{reflect_constant_string}% +\begin{itemdecl} +template + consteval info reflect_constant_string(R&& r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{CharT} be \tcode{ranges::range_value_t}. + +\pnum +\mandates +\tcode{CharT} is one of +\tcode{char}, +\tcode{wchar_t}, +\tcode{char8_t}, +\tcode{char16_t}, +\tcode{char32_t}. + +\pnum +Let $V$ be the pack of values of type \tcode{CharT} +whose elements are the corresponding elements of \tcode{r}, +except that if \tcode{r} refers to a string literal object, +then $V$ does not include the trailing null terminator of \tcode{r}. + +\pnum +Let $P$ be the template parameter object\iref{temp.param} +of type \tcode{const CharT[sizeof...(V)+1]} +initialized with \tcode{$V$..., CHART()}. + +\pnum +\returns +\tcode{\reflexpr{$P$}}. + +\pnum +\begin{note} +$P$ is a potentially non-unique object\iref{intro.object}. +\end{note} +\end{itemdescr} + +\indexlibraryglobal{reflect_constant_array}% +\begin{itemdecl} +template + consteval info reflect_constant_array(R&& r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{T} be \tcode{ranges::range_value_t}. + +\pnum +\mandates +\tcode{T} is a structural type\iref{temp.param}, +\tcode{is_constructible_v>} is \tcode{true}, and +\tcode{is_copy_constructible_v} is \tcode{true}. + +\pnum +\constantwhen +\tcode{reflect_constant(e)} is a constant subexpression +for every element \tcode{e} of \tcode{r}. + +\pnum +Let $V$ be the pack of values of type \tcode{info} +of the same size as \tcode{r}, +where the $i^\text{th}$ element is \tcode{reflect_constant($\tcode{e}_i$)}, +where $\tcode{e}_i$ is the $i^\text{th}$ element of \tcode{r}. + +\pnum +Let $P$ be +\begin{itemize} +\item + If \tcode{sizeof...($V$) > 0} is true, + then the template parameter object\iref{temp.param} + of type \tcode{const T[\brk{}sizeof...(\brk{}$V$)]} + initialized with \tcode{\{[:$V$:]...\}}. +\item + Otherwise, the template parameter object + of type \tcode{array} + initialized with \tcode{\{\}}. +\end{itemize} + +\pnum +\returns +\tcode{\reflexpr{$P$}}. + +\pnum +\begin{note} +$P$ is a potentially non-unique object\iref{intro.object}. +\end{note} +\end{itemdescr} + \rSec2[meta.reflection.define.aggregate]{Reflection class definition generation} \indexlibraryglobal{data_member_options}% diff --git a/source/support.tex b/source/support.tex index b24a209cf0..a7f5254026 100644 --- a/source/support.tex +++ b/source/support.tex @@ -646,6 +646,7 @@ #define @\defnlibxname{cpp_lib_copyable_function}@ 202306L // also in \libheader{functional} #define @\defnlibxname{cpp_lib_coroutine}@ 201902L // freestanding, also in \libheader{coroutine} #define @\defnlibxname{cpp_lib_debugging}@ 202403L // freestanding, also in \libheader{debugging} +#define @\defnlibxname{cpp_lib_define_static}@ 202506L // freestanding, also in \libheader{meta} #define @\defnlibxname{cpp_lib_destroying_delete}@ 201806L // freestanding, also in \libheader{new} #define @\defnlibxname{cpp_lib_enable_shared_from_this}@ 201603L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_endian}@ 201907L // freestanding, also in \libheader{bit}