Skip to content

Commit abb32b2

Browse files
committed
P3491R3 define_static_{string,object,array}
1 parent d7ff520 commit abb32b2

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
@@ -2742,6 +2760,13 @@
27422760
template<class T>
27432761
consteval info reflect_function(T& fn);
27442762

2763+
// \ref{meta.reflection.array}, promoting to static storage
2764+
template<ranges::@\libconcept{input_range}@ R>
2765+
consteval info reflect_constant_string(R&& r);
2766+
2767+
template<ranges::@\libconcept{input_range}@ R>
2768+
consteval info reflect_constant_array(R&& r);
2769+
27452770
// \ref{meta.reflection.define.aggregate}, class definition generation
27462771
struct data_member_options;
27472772
consteval info data_member_spec(info type, data_member_options options);
@@ -2917,6 +2942,7 @@
29172942
// \ref{meta.reflection.annotation}, annotation reflection
29182943
consteval vector<info> annotations_of(info item);
29192944
consteval vector<info> annotations_of_with_type(info item, info type);
2945+
}
29202946
}
29212947
\end{codeblock}
29222948

@@ -2972,6 +2998,107 @@
29722998
\end{codeblock}
29732999
\end{example}
29743000

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

29773104
\begin{itemdecl}
@@ -5334,6 +5461,118 @@
53345461
A reflection of the function designated by \tcode{fn}.
53355462
\end{itemdescr}
53365463

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

53395578
\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)