Skip to content

Commit 46c5455

Browse files
Eisenwavetkoeppe
authored andcommitted
P3491R3 define_static_{string,object,array}
1 parent 69d8608 commit 46c5455

File tree

3 files changed

+252
-4
lines changed

3 files changed

+252
-4
lines changed

source/basic.tex

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3596,9 +3596,17 @@
35963596

35973597
\pnum
35983598
An object is a \defnadj{potentially non-unique}{object} if it is
3599-
a string literal object\iref{lex.string},
3600-
the backing array of an initializer list\iref{dcl.init.ref}, or
3601-
a subobject thereof.
3599+
\begin{itemize}
3600+
\item
3601+
a string literal object\iref{lex.string},
3602+
\item
3603+
the backing array of an initializer list\iref{dcl.init.ref}, or
3604+
\item
3605+
the object introduced by a call to \tcode{std::meta::reflect_constant_array}
3606+
or \tcode{std::meta::\brk{}reflect_con\-stant_string}\iref{meta.reflection.array}, or
3607+
\item
3608+
a subobject thereof.
3609+
\end{itemize}
36023610

36033611
\pnum
36043612
\indextext{most derived object!bit-field}%

source/meta.tex

Lines changed: 240 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2579,7 +2579,25 @@
25792579
\begin{codeblock}
25802580
#include <initializer_list> // see \ref{initializer.list.syn}
25812581

2582-
namespace std::meta {
2582+
namespace std {
2583+
// \ref{meta.string.literal}, checking string literals
2584+
consteval bool is_string_literal(const char* p);
2585+
consteval bool is_string_literal(const wchar_t* p);
2586+
consteval bool is_string_literal(const char8_t* p);
2587+
consteval bool is_string_literal(const char16_t* p);
2588+
consteval bool is_string_literal(const char32_t* p);
2589+
2590+
// \ref{meta.define.static}, promoting to static storage
2591+
template<ranges::@\libconcept{input_range}@ R>
2592+
consteval const ranges::range_value_t<R>* define_static_string(R&& r);
2593+
template<ranges::@\libconcept{input_range}@ R>
2594+
consteval span<const ranges::range_value_t<R>> define_static_array(R&& r);
2595+
template<class T>
2596+
consteval const remove_cvref_t<T>* define_static_object(T&& r);
2597+
2598+
%FIXME: indent the contents of this namespace with two spaces.
2599+
%This is currently not done to make reviewing easier and to avoid merge conflicts.
2600+
namespace meta {
25832601
using info = decltype(^^::);
25842602

25852603
// \ref{meta.reflection.operators}, operator representations
@@ -2744,6 +2762,13 @@
27442762
template<class T>
27452763
consteval info reflect_function(T& fn);
27462764

2765+
// \ref{meta.reflection.array}, promoting to static storage
2766+
template<ranges::@\libconcept{input_range}@ R>
2767+
consteval info reflect_constant_string(R&& r);
2768+
2769+
template<ranges::@\libconcept{input_range}@ R>
2770+
consteval info reflect_constant_array(R&& r);
2771+
27472772
// \ref{meta.reflection.define.aggregate}, class definition generation
27482773
struct data_member_options;
27492774
consteval info data_member_spec(info type, data_member_options options);
@@ -2919,6 +2944,7 @@
29192944
// \ref{meta.reflection.annotation}, annotation reflection
29202945
consteval vector<info> annotations_of(info item);
29212946
consteval vector<info> annotations_of_with_type(info item, info type);
2947+
}
29222948
}
29232949
\end{codeblock}
29242950

@@ -2974,6 +3000,107 @@
29743000
\end{codeblock}
29753001
\end{example}
29763002

3003+
\rSec2[meta.string.literal]{Checking string literals}
3004+
3005+
\indexlibraryglobal{is_string_literal}%
3006+
\begin{itemdecl}
3007+
consteval bool is_string_literal(const char* p);
3008+
consteval bool is_string_literal(const wchar_t* p);
3009+
consteval bool is_string_literal(const char8_t* p);
3010+
consteval bool is_string_literal(const char16_t* p);
3011+
consteval bool is_string_literal(const char32_t* p);
3012+
\end{itemdecl}
3013+
3014+
\begin{itemdescr}
3015+
\pnum
3016+
\returns
3017+
\begin{itemize}
3018+
\item
3019+
If \tcode{p} points to an unspecified object\iref{expr.const},
3020+
\tcode{false}.
3021+
\item
3022+
Otherwise, if \tcode{p} points to a subobject
3023+
of a string literal object\iref{lex.string},
3024+
\tcode{true}.
3025+
\item
3026+
Otherwise, \tcode{false}.
3027+
\end{itemize}
3028+
\end{itemdescr}
3029+
3030+
%FIXME: weird capitalization;
3031+
%pretty sure titles are supposed to be sentence case
3032+
%also this title is duplicated (see fixme below)
3033+
\rSec2[meta.define.static]{Promoting to Static Storage}
3034+
3035+
\pnum
3036+
%FIXME: subclause, not clause
3037+
%FIXME: I take issue with the phrasing for the same reason as in the fixme below (meta.reflection.array)
3038+
The functions in this clause promote compile-time storage into static storage.
3039+
3040+
\indexlibraryglobal{define_static_string}%
3041+
\begin{itemdecl}
3042+
template<ranges::@\libconcept{input_range}@ R>
3043+
consteval const ranges::range_value_t<R>* define_static_string(R&& r);
3044+
\end{itemdecl}
3045+
3046+
\begin{itemdescr}
3047+
\pnum
3048+
\effects
3049+
Equivalent to:
3050+
\begin{codeblock}
3051+
return extract<const ranges::range_value_t<R>*>(meta::reflect_constant_string(r));
3052+
\end{codeblock}
3053+
\end{itemdescr}
3054+
3055+
\indexlibraryglobal{define_static_array}%
3056+
\begin{itemdecl}
3057+
template<ranges::@\libconcept{input_range}@ R>
3058+
consteval span<const ranges::range_value_t<R>> define_static_array(R&& r);
3059+
\end{itemdecl}
3060+
3061+
\begin{itemdescr}
3062+
\pnum
3063+
\effects
3064+
Equivalent to:
3065+
\begin{codeblock}
3066+
using T = ranges::range_value_t<R>;
3067+
meta::info array = meta::reflect_constant_array(r);
3068+
if (is_array_type(type_of(array))) {
3069+
return span<const T>(extract<const T*>(array), extent(type_of(array)));
3070+
} else {
3071+
return span<const T>();
3072+
}
3073+
\end{codeblock}
3074+
\end{itemdescr}
3075+
3076+
\indexlibraryglobal{define_static_object}%
3077+
\begin{itemdecl}
3078+
template<class T>
3079+
consteval const remove_cvref_t<T>* define_static_object(T&& t);
3080+
\end{itemdecl}
3081+
3082+
\begin{itemdescr}
3083+
\pnum
3084+
\effects
3085+
Equivalent to:
3086+
\begin{codeblock}
3087+
using U = remove_cvref_t<T>;
3088+
if constexpr (is_class_type(^^U)) {
3089+
return addressof(extract<const U&>(meta::reflect_constant(std::forward<T>(t))));
3090+
} else {
3091+
return define_static_array(span(addressof(t), 1)).data();
3092+
}
3093+
\end{codeblock}
3094+
3095+
\pnum
3096+
\begin{note}
3097+
For class types,
3098+
\tcode{define_static_object} provides
3099+
the address of the template parameter object\iref{temp.param}
3100+
that is template-argument equivalent to \tcode{t}.
3101+
\end{note}
3102+
\end{itemdescr}
3103+
29773104
\rSec2[meta.reflection.operators]{Operator representations}
29783105

29793106
\begin{itemdecl}
@@ -5368,6 +5495,118 @@
53685495
A reflection of the function designated by \tcode{fn}.
53695496
\end{itemdescr}
53705497

5498+
%FIXME: inconsistent title case;
5499+
%I'm pretty sure we normally use sentence case.
5500+
%Also, this title is duplicated and weird.
5501+
%Why isn't this called "array reflection" in the style of the subclause above?
5502+
\rSec2[meta.reflection.array]{Promoting to Static Storage}
5503+
5504+
%FIXME: We generally don't like "compile-time".
5505+
%This sentence is pretty nonsensical because these terms aren't mutually exclusive.
5506+
%
5507+
%We also deal with ranges as input, and ranges aren't necessarily backed by
5508+
%storage (except for an empty class).
5509+
%
5510+
%Maybe we could say something along the lines of converting ranges of structural types
5511+
%into arrays, during program translation.
5512+
\pnum
5513+
The functions in this subclause promote compile-time storage into static storage.
5514+
5515+
\indexlibraryglobal{reflect_constant_string}%
5516+
\begin{itemdecl}
5517+
template<ranges::@\libconcept{input_range}@ R>
5518+
consteval info reflect_constant_string(R&& r);
5519+
\end{itemdecl}
5520+
5521+
\begin{itemdescr}
5522+
\pnum
5523+
Let \tcode{CharT} be \tcode{ranges::range_value_t<R>}.
5524+
5525+
\pnum
5526+
\mandates
5527+
\tcode{CharT} is one of
5528+
%FIXME: this is kinda silly; we have the defined term "character type"
5529+
%which matches this set exactly.
5530+
%We may as well use it.
5531+
\tcode{char},
5532+
\tcode{wchar_t},
5533+
\tcode{char8_t},
5534+
\tcode{char16_t},
5535+
\tcode{char32_t}.
5536+
5537+
\pnum
5538+
Let $V$ be the pack of values of type \tcode{CharT}
5539+
whose elements are the corresponding elements of \tcode{r},
5540+
except that if \tcode{r} refers to a string literal object,
5541+
then $V$ does not include the trailing null terminator of \tcode{r}.
5542+
5543+
\pnum
5544+
Let $P$ be the template parameter object\iref{temp.param}
5545+
of type \tcode{const CharT[sizeof...(V)+1]}
5546+
initialized with \tcode{$V$..., CHART()}.
5547+
5548+
\pnum
5549+
\returns
5550+
\tcode{\reflexpr{$P$}}.
5551+
5552+
\pnum
5553+
\begin{note}
5554+
$P$ is a potentially non-unique object\iref{intro.object}.
5555+
\end{note}
5556+
\end{itemdescr}
5557+
5558+
\indexlibraryglobal{reflect_constant_array}%
5559+
\begin{itemdecl}
5560+
template<ranges::@\libconcept{input_range}@ R>
5561+
consteval info reflect_constant_array(R&& r);
5562+
\end{itemdecl}
5563+
5564+
\begin{itemdescr}
5565+
\pnum
5566+
Let \tcode{T} be \tcode{ranges::range_value_t<R>}.
5567+
5568+
\pnum
5569+
\mandates
5570+
\tcode{T} is a structural type\iref{temp.param},
5571+
\tcode{is_constructible_v<T, ranges::range_reference_t<R>>} is \tcode{true}, and
5572+
\tcode{is_copy_constructible_v<T>} is \tcode{true}.
5573+
5574+
\pnum
5575+
\constantwhen
5576+
\tcode{reflect_constant(e)} is a constant subexpression
5577+
for every element \tcode{e} of \tcode{r}.
5578+
5579+
\pnum
5580+
Let $V$ be the pack of values of type \tcode{info}
5581+
of the same size as \tcode{r},
5582+
where the $i^\text{th}$ element is \tcode{reflect_constant($\tcode{e}_i$)},
5583+
where $\tcode{e}_i$ is the $i^\text{th}$ element of \tcode{r}.
5584+
5585+
\pnum
5586+
Let $P$ be
5587+
\begin{itemize}
5588+
\item
5589+
If \tcode{sizeof...($V$) > 0},
5590+
%FIXME: is true
5591+
then the template parameter object\iref{temp.param}
5592+
of type \tcode{const T[\brk{}sizeof...(\brk{}$V$)]}
5593+
initialized with \tcode{\{[:$V$:]...\}}.
5594+
\item
5595+
Otherwise, the template parameter object
5596+
of type \tcode{array<T, 0>}
5597+
initialized with \tcode{\{\}}.
5598+
\end{itemize}
5599+
5600+
\pnum
5601+
\returns
5602+
\tcode{\reflexpr{$P$}}.
5603+
5604+
\pnum
5605+
\begin{note}
5606+
$P$ is a potentially non-unique object\iref{intro.object}.
5607+
\end{note}
5608+
\end{itemdescr}
5609+
53715610
\rSec2[meta.reflection.define.aggregate]{Reflection class definition generation}
53725611

53735612
\indexlibraryglobal{data_member_options}%

source/support.tex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,7 @@
646646
#define @\defnlibxname{cpp_lib_copyable_function}@ 202306L // also in \libheader{functional}
647647
#define @\defnlibxname{cpp_lib_coroutine}@ 201902L // freestanding, also in \libheader{coroutine}
648648
#define @\defnlibxname{cpp_lib_debugging}@ 202403L // freestanding, also in \libheader{debugging}
649+
#define @\defnlibxname{cpp_lib_define_static}@ 202506L // freestanding, also in \libheader{meta}
649650
#define @\defnlibxname{cpp_lib_destroying_delete}@ 201806L // freestanding, also in \libheader{new}
650651
#define @\defnlibxname{cpp_lib_enable_shared_from_this}@ 201603L // also in \libheader{memory}
651652
#define @\defnlibxname{cpp_lib_endian}@ 201907L // freestanding, also in \libheader{bit}

0 commit comments

Comments
 (0)