Skip to content

Commit 56dd211

Browse files
committed
P3491R3 define_static_{string,object,array}
1 parent 29d39cd commit 56dd211

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

2762+
// \ref{meta.reflection.array}, promoting to static storage
2763+
template<ranges::@\libconcept{input_range}@ R>
2764+
consteval info reflect_constant_string(R&& r);
2765+
2766+
template<ranges::@\libconcept{input_range}@ R>
2767+
consteval info reflect_constant_array(R&& r);
2768+
27442769
// \ref{meta.reflection.define.aggregate}, class definition generation
27452770
struct data_member_options;
27462771
consteval info data_member_spec(info type, data_member_options options);
@@ -2912,6 +2937,7 @@
29122937
consteval info variant_alternative(size_t index, info type);
29132938

29142939
consteval strong_ordering type_order(info type_a, info type_b);
2940+
}
29152941
}
29162942
\end{codeblock}
29172943

@@ -2967,6 +2993,107 @@
29672993
\end{codeblock}
29682994
\end{example}
29692995

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

29723099
\begin{itemdecl}
@@ -5316,6 +5443,118 @@
53165443
A reflection of the function designated by \tcode{fn}.
53175444
\end{itemdescr}
53185445

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

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