diff --git a/source/algorithms.tex b/source/algorithms.tex index 5218902777..b847e23eac 100644 --- a/source/algorithms.tex +++ b/source/algorithms.tex @@ -233,7 +233,9 @@ \end{codeblock} For each iterator \tcode{i} and sentinel \tcode{s} produced from a range \tcode{r}, -the semantics of \tcode{s - i} has the same type, value, and value category +the semantics of \tcode{s - i} +are the same as those of an expression that +has the same type, value, and value category as \tcode{ranges::distance(i, s)}. \begin{note} The implementation can use \tcode{ranges::distance(r)} @@ -379,7 +381,9 @@ \tcode{BinaryOperation1}, \tcode{BinaryOperation2}, \tcode{BinaryDivideOp}, or -constrained by a concept that subsumes \libconcept{regular_invocable} +constrained by a concept +whose semantic requirements include +that the type models \libconcept{regular_invocable} and the operators used by the analogous overloads to these parallel algorithms that are formed by an invocation with the specified default predicate or operation (where applicable) @@ -2097,13 +2101,13 @@ namespace ranges { template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, - class T1 = projected_value_t, class T2 = T1> + class T1 = projected_value_t, class T2 = iter_value_t> requires @\libconcept{indirectly_writable}@ && @\libconcept{indirect_binary_predicate}@, const T1*> constexpr I replace(I first, S last, const T1& old_value, const T2& new_value, Proj proj = {}); template<@\libconcept{input_range}@ R, class Proj = identity, - class T1 = projected_value_t, Proj>, class T2 = T1> + class T1 = projected_value_t, Proj>, class T2 = range_value_t> requires @\libconcept{indirectly_writable}@, const T2&> && @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> @@ -2111,13 +2115,14 @@ replace(R&& r, const T1& old_value, const T2& new_value, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, - class Proj = identity, class T1 = projected_value_t, class T2 = T1> + class Proj = identity, + class T1 = projected_value_t, class T2 = iter_value_t> requires @\libconcept{indirectly_writable}@ && @\libconcept{indirect_binary_predicate}@, const T1*> I replace(Ep&& exec, I first, S last, const T1& old_value, const T2& new_value, Proj proj = {}); // freestanding-deleted template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, - class T1 = projected_value_t, Proj>, class T2 = T1> + class T1 = projected_value_t, Proj>, class T2 = range_value_t> requires @\libconcept{indirectly_writable}@, const T2&> && @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> @@ -2126,24 +2131,24 @@ Proj proj = {}); // freestanding-deleted template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, - class T = projected_value_t, + class T = iter_value_t, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{indirectly_writable}@ constexpr I replace_if(I first, S last, Pred pred, const T& new_value, Proj proj = {}); - template<@\libconcept{input_range}@ R, class Proj = identity, class T = projected_value_t, + template<@\libconcept{input_range}@ R, class Proj = identity, class T = range_value_t, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> requires @\libconcept{indirectly_writable}@, const T&> constexpr borrowed_iterator_t replace_if(R&& r, Pred pred, const T& new_value, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, - class Proj = identity, class T = projected_value_t, + class Proj = identity, class T = iter_value_t, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{indirectly_writable}@ I replace_if(Ep&& exec, I first, S last, Pred pred, const T& new_value, Proj proj = {}); // freestanding-deleted template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, - class T = projected_value_t, Proj>, + class T = range_value_t, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> requires @\libconcept{indirectly_writable}@, const T&> borrowed_iterator_t @@ -7149,26 +7154,26 @@ Predicate pred, const T& new_value); template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, - class T1 = projected_value_t, class T2 = T1> + class T1 = projected_value_t, class T2 = iter_value_t> requires @\libconcept{indirectly_writable}@ && @\libconcept{indirect_binary_predicate}@, const T1*> constexpr I ranges::replace(I first, S last, const T1& old_value, const T2& new_value, Proj proj = {}); template<@\libconcept{input_range}@ R, class Proj = identity, - class T1 = projected_value_t, Proj>, class T2 = T1> + class T1 = projected_value_t, Proj>, class T2 = range_value_t> requires @\libconcept{indirectly_writable}@, const T2&> && @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> constexpr borrowed_iterator_t ranges::replace(R&& r, const T1& old_value, const T2& new_value, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, - class Proj = identity, class T1 = projected_value_t, class T2 = T1> + class Proj = identity, class T1 = projected_value_t, class T2 = iter_value_t> requires @\libconcept{indirectly_writable}@ && @\libconcept{indirect_binary_predicate}@, const T1*> I ranges::replace(Ep&& exec, I first, S last, const T1& old_value, const T2& new_value, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, - class T1 = projected_value_t, Proj>, class T2 = T1> + class T1 = projected_value_t, Proj>, class T2 = range_value_t> requires @\libconcept{indirectly_writable}@, const T2&> && @\libconcept{indirect_binary_predicate}@, Proj>, const T1*> @@ -7177,24 +7182,24 @@ Proj proj = {}); template<@\libconcept{input_iterator}@ I, @\libconcept{sentinel_for}@ S, class Proj = identity, - class T = projected_value_t, + class T = iter_value_t, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{indirectly_writable}@ constexpr I ranges::replace_if(I first, S last, Pred pred, const T& new_value, Proj proj = {}); -template<@\libconcept{input_range}@ R, class Proj = identity, class T = projected_value_t, Proj>, +template<@\libconcept{input_range}@ R, class Proj = identity, class T = range_value_t, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> requires @\libconcept{indirectly_writable}@, const T&> constexpr borrowed_iterator_t ranges::replace_if(R&& r, Pred pred, const T& new_value, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\libconcept{random_access_iterator}@ I, @\libconcept{sized_sentinel_for}@ S, - class Proj = identity, class T = projected_value_t, + class Proj = identity, class T = iter_value_t, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{indirectly_writable}@ I ranges::replace_if(Ep&& exec, I first, S last, Pred pred, const T& new_value, Proj proj = {}); template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{sized-random-access-range}@ R, class Proj = identity, - class T = projected_value_t, Proj>, + class T = range_value_t, @\libconcept{indirect_unary_predicate}@, Proj>> Pred> requires @\libconcept{indirectly_writable}@, const T&> borrowed_iterator_t @@ -8256,7 +8261,8 @@ \effects Equivalent to: \begin{codeblock} -return ranges::rotate(std::forward(exec), ranges::begin(r), middle, ranges::end(r)); +return ranges::rotate(std::forward(exec), ranges::begin(r), middle, + ranges::begin(r) + ranges::distance(r)); \end{codeblock} \end{itemdescr} @@ -8381,8 +8387,10 @@ \effects Equivalent to: \begin{codeblock} -return ranges::rotate_copy(std::forward(exec), ranges::begin(r), middle, ranges::end(r), - ranges::begin(result_r), ranges::end(result_r)); +return ranges::rotate_copy(std::forward(exec), ranges::begin(r), middle, + ranges::begin(r) + ranges::distance(r), + ranges::begin(result_r), + ranges::begin(result_r) + ranges::distance(result_r)); \end{codeblock} \end{itemdescr} @@ -9002,7 +9010,8 @@ Equivalent to: \begin{codeblock} return ranges::partial_sort(std::forward(exec), ranges::begin(r), middle, - ranges::end(r), comp, proj); + ranges::begin(r) + ranges::distance(r), + comp, proj); \end{codeblock} \end{itemdescr} @@ -9386,7 +9395,8 @@ \effects Equivalent to: \begin{codeblock} -return ranges::nth_element(std::forward(exec), ranges::begin(r), nth, ranges::end(r), +return ranges::nth_element(std::forward(exec), ranges::begin(r), nth, + ranges::begin(r) + ranges::distance(r), comp, proj); \end{codeblock} \end{itemdescr} @@ -9954,14 +9964,14 @@ \pnum \returns -Let \tcode{o1} be the iterator past the last copied element -in the output range \range{out_true}{last_true}, -and \tcode{o2} be the iterator past the last copied element -in the output range \range{out_false}{last_false}. +Let \tcode{$Q$} be the number of elements copied +into the output range \range{out_true}{last_true}, +and \tcode{$V$} be the number of elements copied +into the output range \range{out_false}{last_false}. Returns: \begin{itemize} -\item \tcode{\{o1, o2\}} for the overloads in namespace \tcode{std}. -\item \tcode{\{first + $N$, o1, o2\}} for the overloads in namespace \tcode{ranges}. +\item \tcode{\{out_true + $Q$, out_false + $V$\}} for the overloads in namespace \tcode{std}. +\item \tcode{\{first + $N$, out_true + $Q$, out_false + $V$\}} for the overloads in namespace \tcode{ranges}. \end{itemize} \pnum @@ -10091,12 +10101,12 @@ \tcode{proj2} be \tcode{identity\{\}}, for the overloads with no parameters by those names; \item - $E(\tcode{e1}, \tcode{e1})$ be \tcode{bool(invoke(comp, invoke(proj2, e2), invoke(proj1, e1)))}; + $E$ be \tcode{bool(invoke(comp, invoke(proj2, e2), invoke(proj1, e1)))}; \item $K$ be the smallest integer in \range{0}{last1 - first1} such that for the element \tcode{e1} in the position \tcode{first1 + $K$} there are at least $N - K$ elements \tcode{e2} - in \range{first2}{last2} for which $E(\tcode{e1}, \tcode{e1})$ holds, + in \range{first2}{last2} for which $E$ holds, and be equal to \tcode{last1 - first1} if no such integer exists. \begin{note} @@ -10121,7 +10131,7 @@ If \tcode{e1} is an element of \range{first1}{last1} and \tcode{e2} of \range{first2}{last2}, \tcode{e2} is copied into the output range before \tcode{e1} -if and only if $E(\tcode{e1}, \tcode{e1})$ is \tcode{true}. +if and only if $E$ is \tcode{true}. \pnum \returns @@ -10258,7 +10268,8 @@ Equivalent to: \begin{codeblock} return ranges::inplace_merge(std::forward(exec), ranges::begin(r), middle, - ranges::end(r), comp, proj); + ranges::begin(r) + ranges::distance(r), + comp, proj); \end{codeblock} \end{itemdescr} @@ -13535,7 +13546,7 @@ } template - decltype(auto) @\exposid{deref-move}@(I& it) { + constexpr decltype(auto) @\exposid{deref-move}@(I& it) { if constexpr (is_lvalue_reference_v) return std::move(*it); else diff --git a/source/containers.tex b/source/containers.tex index 148d3de34e..553bc2c4c9 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -1810,6 +1810,9 @@ \mandates \tcode{\libconcept{assignable_from}>} is modeled. +For \tcode{inplace_vector}, +if \tcode{ranges::size(rg)} is a constant expression then +\tcode{ranges::size(rg)} $\le$ \tcode{a.max_size()}. \pnum \expects @@ -10994,6 +10997,11 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +If \tcode{ranges::size(rg)} is a constant expression then +\tcode{ranges::size(rg)} $\le$ \tcode{N}. + \pnum \effects Constructs an \tcode{inplace_vector} with @@ -21940,7 +21948,7 @@ extents_type>) mapping(const LayoutLeftPaddedMapping&) noexcept; template - constexpr explicit(extents_type::rank() > 0) + constexpr explicit(@\seebelow@) mapping(const layout_stride::mapping&); constexpr mapping& operator=(const mapping&) noexcept = default; @@ -22116,7 +22124,7 @@ \indexlibraryctor{layout_left::mapping}% \begin{itemdecl} template - constexpr explicit(extents_type::rank() > 0) + constexpr explicit(@\seebelow@) mapping(const layout_stride::mapping& other); \end{itemdecl} @@ -22141,6 +22149,13 @@ \pnum \effects Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. + +\pnum +\remarks +The expression inside \tcode{explicit} is equivalent to: +\begin{codeblock} +!(extents_type::rank() == 0 && is_convertible_v) +\end{codeblock} \end{itemdescr} \rSec5[mdspan.layout.left.obs]{Observers} @@ -22262,7 +22277,7 @@ extents_type>) mapping(const LayoutRightPaddedMapping&) noexcept; template - constexpr explicit(extents_type::rank() > 0) + constexpr explicit(@\seebelow@) mapping(const layout_stride::mapping&) noexcept; constexpr mapping& operator=(const mapping&) noexcept = default; @@ -22442,7 +22457,7 @@ \indexlibraryctor{layout_right::mapping}% \begin{itemdecl} template - constexpr explicit(extents_type::rank() > 0) + constexpr explicit(@\seebelow@) mapping(const layout_stride::mapping& other) noexcept; \end{itemdecl} @@ -22467,6 +22482,13 @@ \pnum \effects Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. + +\pnum +\remarks +The expression inside \tcode{explicit} is equivalent to: +\begin{codeblock} +!(extents_type::rank() == 0 && is_convertible_v) +\end{codeblock} \end{itemdescr} \rSec5[mdspan.layout.right.obs]{Observers} @@ -22979,7 +23001,7 @@ constexpr explicit(!is_convertible_v) mapping(const layout_left::mapping&); template - constexpr explicit(extents_type::rank() > 0) + constexpr explicit(@\seebelow@) mapping(const layout_stride::mapping&); template constexpr explicit(@\seebelow@) @@ -23268,7 +23290,7 @@ \indexlibraryctor{layout_left_padded::mapping}% \begin{itemdecl} template - constexpr explicit(rank_ > 0) + constexpr explicit(@\seebelow@) mapping(const layout_stride::mapping& other); \end{itemdecl} @@ -23313,6 +23335,13 @@ direct-non-list-initializes \exposid{stride-1} with \tcode{other.stride(1)}. \end{itemize} + +\pnum +\remarks +The expression inside \tcode{explicit} is equivalent to: +\begin{codeblock} +!(rank_ == 0 && is_convertible_v) +\end{codeblock} \end{itemdescr} \indexlibraryctor{layout_left_padded::mapping}% @@ -23375,6 +23404,7 @@ \remarks The expression inside \tcode{explicit} is equivalent to: \begin{codeblock} +!is_convertible_v || rank_> 1 && (padding_value != dynamic_extent || LayoutLeftPaddedMapping::padding_value == dynamic_extent) @@ -23603,7 +23633,7 @@ constexpr explicit(!is_convertible_v) mapping(const layout_right::mapping&); template - constexpr explicit(rank_ > 0) + constexpr explicit(@\seebelow@) mapping(const layout_stride::mapping&); template constexpr explicit(@\seebelow@) @@ -23896,7 +23926,7 @@ \indexlibraryctor{layout_right_padded::mapping}% \begin{itemdecl} template - constexpr explicit(rank_ > 0) + constexpr explicit(@\seebelow@) mapping(const layout_stride::mapping& other); \end{itemdecl} @@ -23942,6 +23972,13 @@ direct-non-list-initializes \exposid{stride-rm2} with \tcode{other.stride(\exposid{rank_} - 2)}. \end{itemize} + +\pnum +\remarks +The expression inside \tcode{explicit} is equivalent to: +\begin{codeblock} +!(rank_ == 0 && is_convertible_v) +\end{codeblock} \end{itemdescr} \indexlibraryctor{layout_right_padded::mapping}% @@ -24004,6 +24041,7 @@ \remarks The expression inside \tcode{explicit} is equivalent to: \begin{codeblock} +!is_convertible_v || @\exposid{rank_}@ > 1 && (padding_value != dynamic_extent || LayoutRightPaddedMapping::padding_value == dynamic_extent) diff --git a/source/exec.tex b/source/exec.tex index 6e99784a93..51766bf9f8 100644 --- a/source/exec.tex +++ b/source/exec.tex @@ -791,8 +791,7 @@ For type \tcode{Sndr} and pack of types \tcode{Env}, let \tcode{CS} be \tcode{completion_signatures_of_t}. Then \tcode{\exposid{single-sender-value-type}} is ill-formed -if \tcode{CS} is ill-formed or -if \tcode{sizeof...(Env) > 1} is \tcode{true}; +if \tcode{CS} is ill-formed; otherwise, it is an alias for: \begin{itemize} \item @@ -1696,7 +1695,8 @@ \item \tcode{(\libconcept{sender} \&\& ...)} \item% \tcode{\libconcept{dependent_sender} || \libconcept{sender_in}}, -where \tcode{Sndr} is \tcode{\exposid{basic-sender}} +where \tcode{Sndr} is +\tcode{\exposid{basic-sender}, decay_t...>} as defined below. \recommended @@ -1981,7 +1981,7 @@ \effects Equivalent to: \begin{codeblock} -(get_completion_signatures<@\exposid{child-type}@, @\exposid{FWD-ENV-T}@(Env)...>(), ...); +((void)get_completion_signatures<@\exposid{child-type}@, @\exposid{FWD-ENV-T}@(Env)...>(), ...); \end{codeblock} \pnum @@ -2003,7 +2003,7 @@ \indexlibrarymember{get_completion_signatures}{\exposid{basic-sender}}% \begin{itemdecl} template - template + template<@\exposconcept{decays-to}@<@\exposid{basic-sender}@> Sndr, class... Env> constexpr auto @\exposid{basic-sender}@::get_completion_signatures(); \end{itemdecl} @@ -3816,7 +3816,7 @@ Equivalent to: \begin{codeblock} auto cs = get_completion_signatures<@\exposid{child-type}@, @\exposid{FWD-ENV-T}@(Env)...>(); -auto fn = [](set_value_t(*)(Ts...)) { +auto fn = [](@\exposid{decayed-typeof}@<@\exposid{set-cpo}@>(*)(Ts...)) { if constexpr (!@\libconcept{invocable}@>, Ts...>) throw @\placeholder{unspecified-exception}@(); }; @@ -4428,22 +4428,24 @@ \begin{codeblock} template constexpr auto @\exposid{make-when-all-env}@(inplace_stop_source& stop_src, // \expos - Env&& env) noexcept { - return @\seebelow@; -} + Env&& env) noexcept; \end{codeblock} -Returns an object \tcode{e} such that + +\pnum +\returns +An object \tcode{e} such that \begin{itemize} \item \tcode{decltype(e)} models \exposconcept{queryable}, and \item \tcode{e.query(get_stop_token)} is expression-equivalent to -\tcode{state.\exposid{stop-src}.get_token()}, and +\tcode{stop_src.get_token()}, and \item given a query object \tcode{q} -with type other than \cv{} \tcode{get_stop_token_t} and -whose type satisfies \exposconceptx{forwarding-\brk{}query}{forwarding-query}, -\tcode{e.query(q)} is expression-equivalent to \tcode{get_env(rcvr).query(q)}. +with type other than \cv{} \tcode{get_stop_token_t}, +\tcode{e.query(q)} is expression-equivalent to \tcode{env.query(q)} +if the type of \tcode{q} satisfies \exposconcept{forwarding-query}, and +ill-formed otherwise. \end{itemize} \pnum @@ -5170,7 +5172,8 @@ if \tcode{remove_cvref_t} models \libconcept{unstoppable_token} then \tcode{\exposid{stop-when}(\brk{}sndr, token)} is expression-equivalent to -\tcode{sndr}. +\tcode{(void)token, sndr}, +except that \tcode{token} and \tcode{sndr} are indeterminately sequenced. \item Otherwise, @@ -6132,7 +6135,7 @@ template static constexpr void @\exposid{for-each}@(Fn&& fn) { // \expos - (std::forward(fn)(static_cast(nullptr)), ...); + (fn(static_cast(nullptr)), ...); } }; @@ -6616,7 +6619,8 @@ template concept @\defexposconcept{awaitable-sender}@ = @\exposconcept{single-sender}@> && - @\libconcept{sender_to}@ && // \seebelow + @\libconcept{sender_to}@::@\exposid{awaitable-receiver}@> && // \seebelow requires (Promise& p) { { p.unhandled_stopped() } -> @\libconcept{convertible_to}@>; }; @@ -6758,16 +6762,8 @@ where \tcode{A} is the type of the expression above. \item Otherwise, \tcode{(void(p), expr)} -if \tcode{\exposconcept{is-awaitable}} is \tcode{true}, -where \tcode{U} is an unspecified class type -that is not \tcode{Promise} and -that lacks a member named \tcode{await_transform}. - -\expects -\tcode{\exposconcept{is-awaitable}} is \tcode{true} and -the expression \tcode{co_await expr} -in a coroutine with promise type \tcode{U} is expression-equivalent to -the same expression in a coroutine with promise type \tcode{Promise}. +if \tcode{decltype(\exposid{GET-AWAITER}(expr))} +satisfies \tcode{\exposconcept{is-awaiter}}. \item Otherwise, \tcode{\exposid{sender-awaitable}\{\exposid{adapted-expr}, p\}} if @@ -7010,6 +7006,9 @@ && @\libconcept{scheduler}@ explicit task_scheduler(Sch&& sch, Allocator alloc = {}); + task_scheduler(const task_scheduler&) = default; + task_scheduler& operator=(const task_scheduler&) = default; + @\exposid{ts-sender}@ schedule(); friend bool operator==(const task_scheduler& lhs, const task_scheduler& rhs) @@ -7029,7 +7028,8 @@ \tcode{task_scheduler} is a class that models \libconcept{scheduler}\iref{exec.sched}. Given an object \tcode{s} of type \tcode{task_scheduler}, let -\tcode{\exposid{SCHED}(s)} be the object owned by \tcode{s.\exposid{sch_}}. +\tcode{\exposid{SCHED}(s)} be the object +pointed to by the pointer owned by \tcode{s.\exposid{sch_}}. \indexlibraryctor{task_scheduler} \begin{itemdecl} diff --git a/source/lib-intro.tex b/source/lib-intro.tex index 2958545e4a..c303a4e992 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -871,7 +871,12 @@ \pnum The type of a customization point object, ignoring cv-qualifiers, shall model -\libconcept{semiregular}\iref{concepts.object}. +\libconcept{semiregular}\iref{concepts.object} +and shall be +a structural type\iref{temp.param} and +a trivially copyable type\iref{class.prop}. +Every constructor of this type +shall have a non-throwing exception specification\iref{except.spec}. \pnum All instances of a specific customization point object type shall diff --git a/source/memory.tex b/source/memory.tex index 1b455e868b..7db5b39d02 100644 --- a/source/memory.tex +++ b/source/memory.tex @@ -507,15 +507,15 @@ template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I, @\exposconcept{nothrow-sized-sentinel-for}@ S> requires @\libconcept{destructible}@> - I destroy(Ep&& exec, I first, S last) noexcept; // freestanding-deleted, + I destroy(Ep&& exec, I first, S last); // freestanding-deleted, // see \ref{algorithms.parallel.overloads} template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-sized-random-access-range}@ R> requires @\libconcept{destructible}@> - borrowed_iterator_t destroy(Ep&& exec, R&& r) noexcept; // freestanding-deleted, + borrowed_iterator_t destroy(Ep&& exec, R&& r); // freestanding-deleted, // see \ref{algorithms.parallel.overloads} template<@\exposconcept{execution-policy}@ Ep, @\exposconcept{nothrow-random-access-iterator}@ I> requires @\libconcept{destructible}@> - I destroy_n(Ep&& exec, I first, iter_difference_t n) noexcept; // freestanding-deleted, + I destroy_n(Ep&& exec, I first, iter_difference_t n); // freestanding-deleted, // see \ref{algorithms.parallel.overloads} } @@ -850,7 +850,7 @@ \indexlibrarymember{pointer_to}{pointer_traits}% \begin{itemdecl} -static pointer pointer_traits::pointer_to(@\seebelow@ r); +static constexpr pointer pointer_traits::pointer_to(@\seebelow@ r); static constexpr pointer pointer_traits::pointer_to(@\seebelow@ r) noexcept; \end{itemdecl} @@ -4416,13 +4416,13 @@ \begin{itemdescr} \pnum \constraints -\tcode{T} is of the form \tcode{U[]}. +\tcode{T} is an array of unknown bound. \pnum \returns -A \tcode{shared_ptr} to an object of type \tcode{U[N]} -with a default initial value, -where \tcode{U} is \tcode{remove_extent_t}. +A \tcode{shared_ptr} to an array of +\tcode{N} elements of type \tcode{remove_extent_t} +with a default initial value. \pnum \begin{example} @@ -4447,7 +4447,7 @@ \begin{itemdescr} \pnum \constraints -\tcode{T} is of the form \tcode{U[N]}. +\tcode{T} is an array of known bound. \pnum \returns @@ -4479,13 +4479,13 @@ \begin{itemdescr} \pnum \constraints -\tcode{T} is of the form \tcode{U[]}. +\tcode{T} is an array of unknown bound. \pnum \returns -A \tcode{shared_ptr} to an object of type \tcode{U[N]}, -where \tcode{U} is \tcode{remove_extent_t} and -each array element has an initial value of \tcode{u}. +A \tcode{shared_ptr} to an array of +\tcode{N} elements of type \tcode{remove_extent_t} +where each array element has an initial value of \tcode{u}. \pnum \begin{example} @@ -4513,7 +4513,7 @@ \begin{itemdescr} \pnum \constraints -\tcode{T} is of the form \tcode{U[N]}. +\tcode{T} is an array of known bound. \pnum \returns @@ -4581,8 +4581,8 @@ \pnum \returns -A \tcode{shared_ptr} to an object of type \tcode{U[N]}, -where \tcode{U} is \tcode{remove_extent_t}. +A \tcode{shared_ptr} to an array of +\tcode{N} elements of type \tcode{remove_extent_t}. \pnum \begin{example} @@ -6441,7 +6441,11 @@ \begin{itemdescr} \pnum \mandates -\tcode{is_copy_constructible_v} is \tcode{true}. +If +\tcode{allocator_traits::propagate_on_container_move_assignment::val\-ue} +is \tcode{false} and +\tcode{allocator_traits::is_always_equal::value} is \tcode{false}, +\tcode{is_move_con\-structible_v} is \tcode{true}. \pnum \effects @@ -6458,28 +6462,20 @@ \item If \tcode{other} is valueless, -\tcode{*this} becomes valueless and -the owned object in \tcode{*this}, if any, -is destroyed using \tcode{allocator_traits::destroy} and -then the storage is deallocated. +\tcode{*this} becomes valueless. \item Otherwise, +if the allocator needs updating or if \tcode{\exposid{alloc} == other.\exposid{alloc}} is \tcode{true}, -swaps the owned objects in \tcode{*this} and \tcode{other}; -the owned object in \tcode{other}, if any, -is then destroyed using \tcode{allocator_traits::destroy} and -then the storage is deallocated. +\tcode{*this} takes ownership of the owned object of \tcode{other}. \item Otherwise, constructs a new owned object with %FIXME: "as the argument as an rvalue" is awkward. the owned object of \tcode{other} as the argument as an rvalue, -using either -the allocator in \tcode{*this} or -the allocator in \tcode{other} -if the allocator needs updating. +using the allocator in \tcode{*this}. \item The previously owned object in \tcode{*this}, if any, @@ -7290,7 +7286,10 @@ \begin{itemdescr} \pnum \mandates -If \tcode{allocator_traits::is_always_equal::value} is \tcode{false}, +If +\tcode{allocator_traits::propagate_on_container_move_assignment::val\-ue} +is \tcode{false} and +\tcode{allocator_traits::is_always_equal::value} is \tcode{false}, \tcode{T} is a complete type. \pnum @@ -7307,22 +7306,19 @@ is \tcode{true}. \item -If \tcode{\exposid{alloc} == other.\exposid{alloc}} is \tcode{true}, -swaps the owned objects in \tcode{*this} and \tcode{other}; -the owned object in \tcode{other}, if any, -is then destroyed using \tcode{allocator_traits::destroy} and -then the storage is deallocated. +If \tcode{other} is valueless, \tcode{*this} becomes valueless. \item Otherwise, -if \tcode{\exposid{alloc} != other.\exposid{alloc}} is \tcode{true}; -if \tcode{other} is not valueless, -a new owned object is constructed in \tcode{*this} -using \tcode{allocator_traits::construct} with -%FIXME: Cleanup wording. -the owned object from \tcode{other} as the argument as an rvalue, -using either the allocator in \tcode{*this} or -the allocator in \tcode{other} if the allocator needs updating. +if the allocator needs updating or +\tcode{\exposid{alloc} == other.\exposid{alloc}} is \tcode{true}, +\tcode{*this} takes ownership of the owned object of \tcode{other}. + +\item +Otherwise, +constructs a new owned object with the owned object of +\tcode{other} as the argument as an rvalue, +using the allocator in \tcode{*this}. \item The previously owned object in \tcode{*this}, if any, diff --git a/source/meta.tex b/source/meta.tex index f0bd37f53d..31fe9d4aa6 100644 --- a/source/meta.tex +++ b/source/meta.tex @@ -778,62 +778,47 @@ // pseudo-mutators template<@\exposconcept{constexpr-param}@ T> constexpr auto operator++(this T) noexcept - requires requires(T::value_type x) { ++x; } - { return constant_wrapper<[] { auto c = T::value; return ++c; }()>{}; } + -> constant_wrapper<++Y> { return {}; } template<@\exposconcept{constexpr-param}@ T> constexpr auto operator++(this T, int) noexcept - requires requires(T::value_type x) { x++; } - { return constant_wrapper<[] { auto c = T::value; return c++; }()>{}; } - + -> constant_wrapper { return {}; } template<@\exposconcept{constexpr-param}@ T> constexpr auto operator--(this T) noexcept - requires requires(T::value_type x) { --x; } - { return constant_wrapper<[] { auto c = T::value; return --c; }()>{}; } + -> constant_wrapper<--Y> { return {}; } template<@\exposconcept{constexpr-param}@ T> constexpr auto operator--(this T, int) noexcept - requires requires(T::value_type x) { x--; } - { return constant_wrapper<[] { auto c = T::value; return c--; }()>{}; } + -> constant_wrapper { return {}; } template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator+=(this T, R) noexcept - requires requires(T::value_type x) { x += R::value; } - { return constant_wrapper<[] { auto v = T::value; return v += R::value; }()>{}; } + constexpr auto operator+=(T, R) noexcept + -> constant_wrapper<(T::value += R::value)> { return {}; } template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator-=(this T, R) noexcept - requires requires(T::value_type x) { x -= R::value; } - { return constant_wrapper<[] { auto v = T::value; return v -= R::value; }()>{}; } + constexpr auto operator-=(T, R) noexcept + -> constant_wrapper<(T::value -= R::value)> { return {}; } template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator*=(this T, R) noexcept - requires requires(T::value_type x) { x *= R::value; } - { return constant_wrapper<[] { auto v = T::value; return v *= R::value; }()>{}; } + constexpr auto operator*=(T, R) noexcept + -> constant_wrapper<(T::value *= R::value)> { return {}; } template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator/=(this T, R) noexcept - requires requires(T::value_type x) { x /= R::value; } - { return constant_wrapper<[] { auto v = T::value; return v /= R::value; }()>{}; } + constexpr auto operator/=(T, R) noexcept + -> constant_wrapper<(T::value /= R::value)> { return {}; } template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator%=(this T, R) noexcept - requires requires(T::value_type x) { x %= R::value; } - { return constant_wrapper<[] { auto v = T::value; return v %= R::value; }()>{}; } + constexpr auto operator%=(T, R) noexcept + -> constant_wrapper<(T::value %= R::value)> { return {}; } template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator&=(this T, R) noexcept - requires requires(T::value_type x) { x &= R::value; } - { return constant_wrapper<[] { auto v = T::value; return v &= R::value; }()>{}; } + constexpr auto operator&=(T, R) noexcept + -> constant_wrapper<(T::value &= R::value)> { return {}; } template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator|=(this T, R) noexcept - requires requires(T::value_type x) { x |= R::value; } - { return constant_wrapper<[] { auto v = T::value; return v |= R::value; }()>{}; } + constexpr auto operator|=(T, R) noexcept + -> constant_wrapper<(T::value |= R::value)> { return {}; } template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator^=(this T, R) noexcept - requires requires(T::value_type x) { x ^= R::value; } - { return constant_wrapper<[] { auto v = T::value; return v ^= R::value; }()>{}; } + constexpr auto operator^=(T, R) noexcept + -> constant_wrapper<(T::value ^= R::value)> { return {}; } template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator<<=(this T, R) noexcept - requires requires(T::value_type x) { x <<= R::value; } - { return constant_wrapper<[] { auto v = T::value; return v <<= R::value; }()>{}; } + constexpr auto operator<<=(T, R) noexcept + -> constant_wrapper<(T::value <<= R::value)> { return {}; } template<@\exposconcept{constexpr-param}@ T, @\exposconcept{constexpr-param}@ R> - constexpr auto operator>>=(this T, R) noexcept - requires requires(T::value_type x) { x >>= R::value; } - { return constant_wrapper<[] { auto v = T::value; return v >>= R::value; }()>{}; } + constexpr auto operator>>=(T, R) noexcept + -> constant_wrapper<(T::value >>= R::value)> { return {}; } }; template<@\exposid{cw-fixed-value}@ X, class> @@ -844,8 +829,7 @@ template<@\exposconcept{constexpr-param}@ R> constexpr auto operator=(R) const noexcept - requires requires(value_type x) { x = R::value; } - { return constant_wrapper<[] { auto v = value; return v = R::value; }()>{}; } + -> constant_wrapper { return {}; } constexpr operator decltype(auto)() const noexcept { return value; } }; @@ -3426,19 +3410,20 @@ \begin{itemdescr} \pnum -Let \tcode{T} be \tcode{ranges::range_value_t}. +Let \tcode{T} be \tcode{ranges::range_value_t} and +$\tcode{e}_i$ be \tcode{static_cast(*$it_i$)}, +where \tcode{$it_i$} is an iterator to the $i^\text{th}$ element of \tcode{r}. \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}. +\tcode{T} satisfies \libconcept{copy_constructible}. \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}. +where the $i^\text{th}$ element is \tcode{reflect_constant($\tcode{e}_i$)}. \pnum Let $P$ be @@ -3460,9 +3445,10 @@ \pnum \throws -\tcode{meta::exception} unless -\tcode{reflect_constant(e)} is a constant subexpression -for every element \tcode{e} of \tcode{r}. +Any exception thrown by the evaluation of any $\tcode{e}_i$, or +\tcode{meta::exception} +if evaluation of any \tcode{reflect_constant($\tcode{e}_i$)} +would exit via an exception. \pnum \begin{note} @@ -3784,8 +3770,19 @@ Otherwise, if \tcode{r} represents an unnamed entity, then \tcode{false}. \item - Otherwise, if \tcode{r} represents a class type, + Otherwise, if \tcode{r} represents a type alias, then \tcode{!has_template_arguments(r)}. +\item + Otherwise, if \tcode{r} represents a type, + then \tcode{true} if + \begin{itemize} + \item + \tcode{r} represents a cv-unqualified class type and + \tcode{has_template_arguments(r)} is \tcode{false}, or + \item + \tcode{r} represents a cv-unqualified enumeration type. + \end{itemize} + Otherwise, \tcode{false}. \item Otherwise, if \tcode{r} represents a function, then \tcode{true} if \tcode{has_template_arguments(r)} is \tcode{false} @@ -3853,9 +3850,6 @@ then \tcode{false} if the declaration of that structured binding was instantiated from a structured binding pack. Otherwise, \tcode{true}. -\item - Otherwise, if \tcode{r} represents a type alias, - then \tcode{!has_template_arguments(r)}. \item Otherwise, if \tcode{r} represents an enumerator, @@ -4404,13 +4398,11 @@ \indexlibraryglobal{has_internal_linkage}% \indexlibraryglobal{has_module_linkage}% \indexlibraryglobal{has_external_linkage}% -\indexlibraryglobal{has_c_language_linkage}% \indexlibraryglobal{has_linkage}% \begin{itemdecl} consteval bool has_internal_linkage(info r); consteval bool has_module_linkage(info r); consteval bool has_external_linkage(info r); -consteval bool has_c_language_linkage(info r); consteval bool has_linkage(info r); \end{itemdecl} @@ -4426,11 +4418,27 @@ whose name has internal linkage, module linkage, -C language linkage, or +external linkage, or any linkage, respectively\iref{basic.link}. Otherwise, \tcode{false}. \end{itemdescr} +\indexlibraryglobal{has_c_language_linkage}% +\begin{itemdecl} +consteval bool has_c_language_linkage(info r); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if \tcode{r} represents a +variable, +function, or +function type +with C language linkage. +Otherwise, \tcode{false}. +\end{itemdescr} + \indexlibraryglobal{is_complete_type}% \begin{itemdecl} consteval bool is_complete_type(info r); @@ -4910,12 +4918,9 @@ \begin{itemdescr} \pnum \returns -A reflection representing the underlying entity of what \tcode{r} represents. - -\pnum -\throws -\tcode{meta::exception} unless -\tcode{r} represents an entity. +If \tcode{r} represents an entity, then +a reflection representing the underlying entity of what \tcode{r} represents. +Otherwise, \tcode{r}. \pnum \begin{example} @@ -5429,14 +5434,8 @@ \pnum \throws \tcode{meta::exception} if -\begin{itemize} -\item \tcode{r} represents a class member - for which \tcode{\exposid{PARENT-CLS}(r)} is an incomplete class or -\item - \tcode{r} represents a direct base class relationship $(D, B)$ - for which $D$ is incomplete. -\end{itemize} + for which \tcode{\exposid{PARENT-CLS}(r)} is an incomplete class. \pnum \begin{example} @@ -5473,13 +5472,14 @@ \pnum \throws -\tcode{meta::exception} unless +\tcode{meta::exception} if \begin{itemize} \item - \tcode{nonstatic_data_members_of(\brk{}r, access_context::\brk{}unchecked())} - is a constant subexpression and + the evaluation of + \tcode{nonstatic_data_members_of(r, access_context::unchecked())} + would exit via an exception or \item - \tcode{r} does not represent a closure type. + \tcode{r} represents a closure type. \end{itemize} \end{itemdescr} @@ -5496,9 +5496,9 @@ \pnum \throws -\tcode{meta::exception} unless +\tcode{meta::exception} if the evaluation of \tcode{bases_of(r, access_context::unchecked())} -is a constant subexpression. +would exit via an exception. \end{itemdescr} \indexlibraryglobal{has_inaccessible_subobjects}% @@ -5901,7 +5901,9 @@ variable of non-reference type, non-static data member that is not a bit-field, direct base class relationship, or -data member description. +data member description +$(T, N, A, W, \mathit{NUA})$\iref{class.mem.general} +where $W$ is $\bot$. \item If \tcode{dealias(r)} represents a type, then \tcode{is_complete_type(r)} is \tcode{true}. @@ -6058,7 +6060,8 @@ \tcode{meta::exception} unless \begin{itemize} \item - \tcode{annotations_of(item)} is a constant expression and + the evaluation of + \tcode{annotations_of(item)} would not exit via an exception and \item \tcode{dealias(type)} represents a type and \tcode{is_complete_type(type)} is \tcode{true}. @@ -6217,6 +6220,19 @@ \rSec2[meta.reflection.substitute]{Reflection substitution} +\pnum +Let \tcode{\placeholder{TARG-SPLICE}(x)} be: +\begin{itemize} +\item +\tcode{template [: x :]} if \tcode{is_template(x)} is \tcode{true}, otherwise + +\item +\tcode{typename [: x :]} if \tcode{is_type(x)} is \tcode{true}, otherwise + +\item +\tcode{([: x :])}. +\end{itemize} + \begin{itemdecl} template concept @\deflibconcept{reflection_range}@ = @@ -6237,7 +6253,7 @@ \pnum \returns -\tcode{true} if \tcode{Z<[:Args:]...>} is a valid \grammarterm{template-id}\iref{temp.names} +\tcode{true} if \tcode{Z<\placeholder{TARG-SPLICE}(Args)...>} is a valid \grammarterm{template-id}\iref{temp.names} that does not name a function whose type contains an undeduced placeholder type. Otherwise, \tcode{false}. @@ -6251,7 +6267,7 @@ \pnum \begin{note} -If forming \tcode{Z<[:Args:]...>} leads to a failure +If forming \tcode{Z<\placeholder{TARG-SPLICE}(Args)...>} leads to a failure outside of the immediate context, the program is ill-formed. \end{note} @@ -6272,7 +6288,7 @@ \pnum \returns -\tcode{\reflexpr{Z<[:Args:]...>}}. +\tcode{\reflexpr{Z<\placeholder{TARG-SPLICE}(Args)...>}}. \pnum \throws @@ -6281,7 +6297,7 @@ \pnum \begin{note} -If forming \tcode{Z<[:Args:]...>} leads to a failure outside of the immediate context, +If forming \tcode{Z<\placeholder{TARG-SPLICE}(Args)...>} leads to a failure outside of the immediate context, the program is ill-formed. \end{note} @@ -6403,9 +6419,11 @@ \pnum \throws -\tcode{meta::exception} unless -\tcode{expr} is suitable for use as a constant template argument -for a constant template parameter of type \tcode{T\&}\iref{temp.arg.nontype}. +\tcode{meta::exception} if +\tcode{E} is not suitable for use as a constant template argument +for a constant template parameter of type \tcode{T\&}\iref{temp.arg.nontype}, +where \tcode{E} is an lvalue constant expression that +computes the object that \tcode{expr} refers to. \end{itemdescr} \indexlibraryglobal{reflect_function}% @@ -6425,9 +6443,11 @@ \pnum \throws -\tcode{meta::exception} unless -\tcode{fn} is suitable for use as a constant template argument -for a constant template parameter of type \tcode{T\&}\iref{temp.arg.nontype}. +\tcode{meta::exception} if +\tcode{F} is not suitable for use as a constant template argument +for a constant template parameter of type \tcode{T\&}\iref{temp.arg.nontype}, +where \tcode{F} is an lvalue constant expression that +computes the function that \tcode{fn} refers to. \end{itemdescr} \rSec2[meta.reflection.define.aggregate]{Reflection class definition generation} @@ -6610,7 +6630,7 @@ \begin{itemdescr} \pnum -Let $C$ be the class represented by \tcode{class_type} +Let $C$ be the type represented by \tcode{class_type} and $r_K$ be the $K^\text{th}$ reflection value in \tcode{mdescrs}. For every $r_K$ in \tcode{mdescrs}, let $(T_K, N_K, A_K, W_K, \mathit{NUA}_K)$ be @@ -6619,6 +6639,8 @@ \pnum \constantwhen \begin{itemize} +\item + \tcode{class_type} represents a cv-unqualified class type; \item $C$ is incomplete from every point in the evaluation context; \begin{note} @@ -6637,9 +6659,9 @@ then either: \begin{itemize} \item - \tcode{$N_K$ != $N_L$} is \tcode{true} or + \tcode{$N_K$} is not the same identifier as \tcode{$N_L$} or \item - \tcode{$N_K$ == u8"_"} is \tcode{true}. + \tcode{$N_K$} is the identifier \tcode{_} (\ucode{005f} low line). \begin{note} Every provided identifier is unique or \tcode{"_"}. \end{note} @@ -6668,6 +6690,7 @@ \item For each $r_K$, there is a corresponding entity $M_K$ + with public access belonging to the class scope of $D$ with the following properties: \begin{itemize} @@ -6675,7 +6698,7 @@ If $N_K$ is $\bot$, $M_K$ is an unnamed bit-field. Otherwise, $M_K$ is a non-static data member whose name is the identifier - determined by the character sequence encoded by $N_K$ in UTF-8. + $N_K$. \item The type of $M_K$ is $T_K$. \item diff --git a/source/numerics.tex b/source/numerics.tex index 9d6bf6e62c..fac70b5e9d 100644 --- a/source/numerics.tex +++ b/source/numerics.tex @@ -11117,20 +11117,6 @@ template auto dotc(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2); - // \ref{linalg.algs.blas1.ssq}, scaled sum of squares of a vector's elements - template - struct sum_of_squares_result { - Scalar scaling_factor; - Scalar scaled_sum_of_squares; - }; - template<@\exposconcept{in-vector}@ InVec, class Scalar> - sum_of_squares_result - vector_sum_of_squares(InVec v, sum_of_squares_result init); - template - sum_of_squares_result - vector_sum_of_squares(ExecutionPolicy&& exec, - InVec v, sum_of_squares_result init); - // \ref{linalg.algs.blas1.nrm2}, Euclidean norm of a vector template<@\exposconcept{in-vector}@ InVec, class Scalar> Scalar vector_two_norm(InVec v, Scalar init); @@ -13736,55 +13722,6 @@ \end{itemize} \end{itemdescr} -\rSec3[linalg.algs.blas1.ssq]{Scaled sum of squares of a vector's elements} - -\indexlibraryglobal{vector_sum_of_squares}% -\begin{itemdecl} -template<@\exposconcept{in-vector}@ InVec, class Scalar> - sum_of_squares_result vector_sum_of_squares(InVec v, sum_of_squares_result init); -template - sum_of_squares_result vector_sum_of_squares(ExecutionPolicy&& exec, - InVec v, sum_of_squares_result init); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\begin{note} -These functions correspond to the LAPACK function \tcode{xLASSQ}\supercite{lapack}. -\end{note} - -\pnum -\mandates -\tcode{decltype(\exposid{abs-if-needed}(declval()))} is convertible to \tcode{Scalar}. - -\pnum -\effects -Returns a value \tcode{result} such that -\begin{itemize} -\item -\tcode{result.scaling_factor} is the maximum of \tcode{init.scaling_factor} and -\tcode{\exposid{abs-if-needed}(x[i])} -for all \tcode{i} in the domain of \tcode{v}; and -\item -let \tcode{s2init} be -\begin{codeblock} -init.scaling_factor * init.scaling_factor * init.scaled_sum_of_squares -\end{codeblock} -then \tcode{result.scaling_factor * result.scaling_factor * result.scaled_sum_of_squares} -equals the sum of \tcode{s2init} and -the squares of \tcode{\exposid{abs-if-needed}(x[i])} -for all \tcode{i} in the domain of \tcode{v}. -\end{itemize} - -\pnum -\remarks -If \tcode{InVec::value_type}, and \tcode{Scalar} -are all floating-point types or specializations of \tcode{complex}, -and if \tcode{Scalar} has higher precision -than \tcode{InVec::value_type}, -then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. -\end{itemdescr} - \rSec3[linalg.algs.blas1.nrm2]{Euclidean norm of a vector} \indexlibraryglobal{vector_two_norm}% @@ -13822,11 +13759,6 @@ and if \tcode{Scalar} has higher precision than \tcode{InVec::value_type}, then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. -\begin{note} -An implementation of this function for floating-point types \tcode{T} -can use the \tcode{scaled_sum_of_squares} result from -\tcode{vector_sum_of_squares(x, \{.scaling_factor=1.0, .scaled_sum_of_squares=init\})}. -\end{note} \end{itemdescr} \indexlibraryglobal{vector_two_norm}% @@ -16223,6 +16155,12 @@ bool_constant::value && bool_constant(T()) == T::value>::value; +template + concept @\defexposconceptnc{explicitly-convertible-to}@ = // \expos + requires { + static_cast(declval()); + }; + template using @\exposidnc{deduced-vec-t} = \seebelownc@; // \expos template using @\exposidnc{make-compatible-simd-t} = \seebelownc@; // \expos @@ -16581,56 +16519,52 @@ flags f = {}); template - requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + requires ranges::@\libconcept{sized_range}@ constexpr void unchecked_store(const basic_vec& v, R&& r, flags f = {}); template - requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + requires ranges::@\libconcept{sized_range}@ constexpr void unchecked_store(const basic_vec& v, R&& r, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); template - requires @\libconcept{indirectly_writable}@ constexpr void unchecked_store(const basic_vec& v, I first, iter_difference_t n, flags f = {}); template - requires @\libconcept{indirectly_writable}@ constexpr void unchecked_store(const basic_vec& v, I first, iter_difference_t n, const typename basic_vec::mask_type& mask, flags f = {}); template S, class... Flags> - requires @\libconcept{indirectly_writable}@ constexpr void unchecked_store(const basic_vec& v, I first, S last, flags f = {}); template S, class... Flags> - requires @\libconcept{indirectly_writable}@ constexpr void unchecked_store(const basic_vec& v, I first, S last, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); template - requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + requires ranges::@\libconcept{sized_range}@ constexpr void partial_store(const basic_vec& v, R&& r, flags f = {}); template - requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + requires ranges::@\libconcept{sized_range}@ constexpr void partial_store(const basic_vec& v, R&& r, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); template - requires @\libconcept{indirectly_writable}@ constexpr void partial_store( const basic_vec& v, I first, iter_difference_t n, flags f = {}); template - requires @\libconcept{indirectly_writable}@ constexpr void partial_store( const basic_vec& v, I first, iter_difference_t n, const typename basic_vec::mask_type& mask, flags f = {}); template S, class... Flags> - requires @\libconcept{indirectly_writable}@ constexpr void partial_store(const basic_vec& v, I first, S last, flags f = {}); template S, class... Flags> - requires @\libconcept{indirectly_writable}@ constexpr void partial_store(const basic_vec& v, I first, S last, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); // \ref{simd.permute.static}, static permute static constexpr @\exposid{simd-size-type}@ @\libmember{zero_element}{simd}@ = @\impdefx{value of \tcode{simd::zero_element}}@; @@ -17555,6 +17489,7 @@ \begin{codeblock} namespace std::simd { template class basic_vec { + using @\exposid{real-type}@ = @\seebelow@; // \expos public: using @\libmember{value_type}{basic_vec}@ = T; using @\libmember{mask_type}{basic_vec}@ = basic_mask; @@ -17583,8 +17518,7 @@ constexpr basic_vec(R&& range, flags = {}); template constexpr basic_vec(R&& range, const mask_type& mask, flags = {}); - template<@\exposconcept{simd-floating-point}@ V> - constexpr explicit(@\seebelow@) basic_vec(const V& reals, const V& imags = {}) noexcept; + constexpr basic_vec(const @\exposid{real-type}@& reals, const @\exposid{real-type}@& imags = {}) noexcept; // \ref{simd.subscr}, \tcode{basic_vec} subscript operators constexpr value_type operator[](@\exposid{simd-size-type}@) const; @@ -17592,12 +17526,10 @@ constexpr resize_t operator[](const I& indices) const; // \ref{simd.complex.access}, \tcode{basic_vec} complex accessors - constexpr auto real() const noexcept; - constexpr auto imag() const noexcept; - template<@\exposconcept{simd-floating-point}@ V> - constexpr void real(const V& v) noexcept; - template<@\exposconcept{simd-floating-point}@ V> - constexpr void imag(const V& v) noexcept; + constexpr @\exposid{real-type}@ real() const noexcept; + constexpr @\exposid{real-type}@ imag() const noexcept; + constexpr void real(const @\exposid{real-type}@& v) noexcept; + constexpr void imag(const @\exposid{real-type}@& v) noexcept; // \ref{simd.unary}, \tcode{basic_vec} unary operators constexpr basic_vec& operator++() noexcept; @@ -17691,6 +17623,12 @@ implementation. \end{note} +\pnum +If \tcode{T} is a specialization of \tcode{complex}, +\exposid{real-type} denotes the same type as +\tcode{rebind_t>}, +otherwise an unspecified non-array object type. + \rSec3[simd.ctor]{Constructors} \indexlibraryctor{basic_vec} @@ -17704,7 +17642,7 @@ \pnum \constraints -\tcode{value_type} satisfies \tcode{\libconcept{constructible_from}}. +\tcode{U} satisfies \tcode{\exposconcept{explicitly-convertible-to}}. \pnum \effects @@ -17738,7 +17676,10 @@ \begin{itemdescr} \pnum \constraints -\tcode{\exposid{simd-size-v} == size()} is \tcode{true}. +\begin{itemize} +\item \tcode{\exposid{simd-size-v} == size()} is \tcode{true}, and +\item \tcode{U} satisfies \tcode{\exposconcept{explicitly-convertible-to}}. +\end{itemize} \pnum \effects @@ -17810,20 +17751,17 @@ \begin{itemize} \item \tcode{R} models \tcode{ranges::\libconcept{contiguous_range}} and \tcode{ranges::\libconcept{sized_range}}, -\item \tcode{ranges::size(r)} is a constant expression, and -\item \tcode{ranges::size(r)} is equal to \tcode{size()}. +\item \tcode{ranges::size(r)} is a constant expression, +\item \tcode{ranges::size(r)} is equal to \tcode{size()}, and +\item \tcode{ranges::range_value_t} is a vectorizable type and + satisfies \tcode{\exposconcept{explicitly-convertible-to}}. \end{itemize} \pnum \mandates -\begin{itemize} - \item - \tcode{ranges::range_value_t} is a vectorizable type, and - \item - if the template parameter pack \tcode{Flags} does not contain - \tcode{\exposid{convert-flag}}, then the conversion from - \tcode{ranges::range_value_t} to \tcode{value_type} is value-preserving. -\end{itemize} +If the template parameter pack \tcode{Flags} does not contain +\tcode{\exposid{convert-flag}}, then the conversion from +\tcode{ranges::range_value_t} to \tcode{value_type} is value-preserving. \pnum \expects @@ -17868,31 +17806,18 @@ \indexlibraryctor{basic_vec} \begin{itemdecl} -template<@\exposconcept{simd-floating-point}@ V> - constexpr explicit(@\seebelow@) - basic_vec(const V& reals, const V& imags = {}) noexcept; +constexpr basic_vec(const @\exposid{real-type}@& reals, const @\exposid{real-type}@& imags = {}) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \constraints -\begin{itemize} - \item - \tcode{\exposconcept{simd-complex}} is modeled, and - \item - \tcode{V::size() == size()} is \tcode{true}. -\end{itemize} +\tcode{\exposconcept{simd-complex}} is modeled. \pnum \effects Initializes the $i^\text{th}$ element with \tcode{value_type(reals[$i$], imags[$i$])} for all $i$ in the range \range{0}{size()}. - -\pnum -\remarks -The expression inside \tcode{explicit} evaluates to \tcode{false} if and only -if the floating-point conversion rank of \tcode{T::value_type} is greater than -or equal to the floating-point conversion rank of \tcode{V::value_type}. \end{itemdescr} \rSec3[simd.subscr]{Subscript operator} @@ -17933,8 +17858,8 @@ \indexlibrarymember{real}{basic_vec} \indexlibrarymember{imag}{basic_vec} \begin{itemdecl} -constexpr auto real() const noexcept; -constexpr auto imag() const noexcept; +constexpr @\exposid{real-type}@ real() const noexcept; +constexpr @\exposid{real-type}@ imag() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -17944,9 +17869,9 @@ \pnum \returns -An object of type \tcode{rebind_t} +An object of type \exposid{real-type} where the $i^\text{th}$ element is initialized to the result of -\tcode{\placeholder{cmplx-func}(operator[]($i$))} for all $i$ in the range +\tcode{\placeholder{cmplx-func}(\brk{}operator[]($i$))} for all $i$ in the range \range{0}{size()}, where \tcode{\placeholder{cmplx-func}} is the corresponding function from \libheader{complex}. \end{itemdescr} @@ -17954,24 +17879,14 @@ \indexlibrarymember{real}{basic_vec} \indexlibrarymember{imag}{basic_vec} \begin{itemdecl} -template<@\exposconcept{simd-floating-point}@ V> - constexpr void real(const V& v) noexcept; -template<@\exposconcept{simd-floating-point}@ V> - constexpr void imag(const V& v) noexcept; +constexpr void real(const @\exposid{real-type}@& v) noexcept; +constexpr void imag(const @\exposid{real-type}@& v) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \constraints -\begin{itemize} - \item - \tcode{\exposconcept{simd-complex}} is modeled, - \item - \tcode{\libconcept{same_as}} - is modeled, and - \item - \tcode{V::size() == size()} is \tcode{true}. -\end{itemize} +\tcode{\exposconcept{simd-complex}} is modeled. \pnum \effects @@ -18559,14 +18474,17 @@ \item \tcode{r} be \tcode{R(first, n)} for the overloads with an \tcode{n} parameter and \tcode{R(first, last)} for the overloads with a \tcode{last} - parameter. + parameter; + \item + \tcode{T} be \tcode{typename V::value_type}. \end{itemize} \pnum \mandates \begin{itemize} \item - \tcode{ranges::range_value_t} is a vectorizable type, + \tcode{ranges::range_value_t} is a vectorizable type and + satisfies \tcode{\exposconcept{explicitly-convertible-to}}, \item \tcode{same_as, V>} is \tcode{true}, \item @@ -18613,28 +18531,27 @@ \indexlibrarymember{unchecked_store}{simd} \begin{itemdecl} template - requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + requires ranges::@\libconcept{sized_range}@ constexpr void unchecked_store(const basic_vec& v, R&& r, flags f = {}); template - requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + requires ranges::@\libconcept{sized_range}@ constexpr void unchecked_store(const basic_vec& v, R&& r, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); template - requires @\libconcept{indirectly_writable}@ constexpr void unchecked_store(const basic_vec& v, I first, iter_difference_t n, flags f = {}); template - requires @\libconcept{indirectly_writable}@ constexpr void unchecked_store(const basic_vec& v, I first, iter_difference_t n, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); template S, class... Flags> - requires @\libconcept{indirectly_writable}@ constexpr void unchecked_store(const basic_vec& v, I first, S last, flags f = {}); template S, class... Flags> - requires @\libconcept{indirectly_writable}@ constexpr void unchecked_store(const basic_vec& v, I first, S last, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); \end{itemdecl} \begin{itemdescr} @@ -18679,28 +18596,27 @@ \indexlibrarymember{partial_store}{simd} \begin{itemdecl} template - requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + requires ranges::@\libconcept{sized_range}@ constexpr void partial_store(const basic_vec& v, R&& r, flags f = {}); template - requires ranges::@\libconcept{sized_range}@ && @\libconcept{indirectly_writable}@, T> + requires ranges::@\libconcept{sized_range}@ constexpr void partial_store(const basic_vec& v, R&& r, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); template - requires @\libconcept{indirectly_writable}@ constexpr void partial_store(const basic_vec& v, I first, iter_difference_t n, flags f = {}); template - requires @\libconcept{indirectly_writable}@ constexpr void partial_store(const basic_vec& v, I first, iter_difference_t n, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); template S, class... Flags> - requires @\libconcept{indirectly_writable}@ constexpr void partial_store(const basic_vec& v, I first, S last, flags f = {}); template S, class... Flags> - requires @\libconcept{indirectly_writable}@ constexpr void partial_store(const basic_vec& v, I first, S last, - const typename basic_vec::mask_type& mask, flags f = {}); + const typename basic_vec::mask_type& mask, + flags f = {}); \end{itemdecl} \begin{itemdescr} @@ -18719,6 +18635,17 @@ parameter. \end{itemize} +\pnum +\constraints +\begin{itemize} + \item + \tcode{ranges::iterator_t} models + \tcode{\libconcept{indirectly_writable}>}, and + \item + \tcode{T} satisfies + \tcode{\exposconcept{explicitly-convertible-to}>}. +\end{itemize} + \pnum \mandates \begin{itemize} @@ -18754,7 +18681,7 @@ \effects For all $i$ in the range of \range{0}{basic_vec::size()}, if \tcode{mask[$i$] \&\& $i$ < ranges::\brk{}size(r)} is \tcode{true}, evaluates -\tcode{ranges::data(r)[$i$] = v[$i$]}. +\tcode{ranges::data(r)[$i$] = static_cast>(v[\brk{}$i$])}. \end{itemdescr} \rSec3[simd.permute.static]{Static permute} @@ -18988,6 +18915,11 @@ \tcode{T} be \tcode{typename V::value_type}. \end{itemize} +\pnum +\constraints +\tcode{ranges::range_value_t} is a vectorizable type and satisfies +\tcode{\exposconceptx{explicitly-convert\-ible-to}{explicitly-convertible-to}}. + \pnum \mandates \begin{itemize} @@ -19079,7 +19011,16 @@ \pnum \constraints -\tcode{V::size() == I::size()} is \tcode{true}. +\begin{itemize} +\item +\tcode{V::size() == I::size()} is \tcode{true}, +\item +\tcode{ranges::iterator_t} models +\tcode{\libconcept{indirectly_writable}>}, and +\item +\tcode{typename V::value_type} satisfies +\tcode{\exposconcept{explicitly-convertible-to}>}. +\end{itemize} \pnum \mandates @@ -19111,7 +19052,7 @@ \effects For all $i$ in the range \range{0}{I::size()}, if \tcode{mask[$i$] \&\& (indices[$i$] < ranges::size(out))} is \tcode{true}, evaluates -\tcode{ranges::data(out)[indices[$i$]] = v[$i$]}. +\tcode{ranges::data(out)[indices[$i$]] = static_cast>(v[\brk{}$i$])}. \end{itemdescr} \rSec3[simd.creation]{Creation} @@ -20053,9 +19994,9 @@ // \ref{simd.mask.unary}, \tcode{basic_mask} unary operators constexpr basic_mask operator!() const noexcept; - constexpr basic_vec<@\exposid{integer-from}@, Abi> operator+() const noexcept; - constexpr basic_vec<@\exposid{integer-from}@, Abi> operator-() const noexcept; - constexpr basic_vec<@\exposid{integer-from}@, Abi> operator~() const noexcept; + constexpr @\seebelow@ operator+() const noexcept; + constexpr @\seebelow@ operator-() const noexcept; + constexpr @\seebelow@ operator~() const noexcept; // \ref{simd.mask.conv}, \tcode{basic_mask} conversions template @@ -20266,9 +20207,9 @@ \indexlibrarymember{operator~}{basic_mask} \begin{itemdecl} constexpr basic_mask operator!() const noexcept; -constexpr basic_vec<@\exposid{integer-from}@, Abi> operator+() const noexcept; -constexpr basic_vec<@\exposid{integer-from}@, Abi> operator-() const noexcept; -constexpr basic_vec<@\exposid{integer-from}@, Abi> operator~() const noexcept; +constexpr @\seebelow@ operator+() const noexcept; +constexpr @\seebelow@ operator-() const noexcept; +constexpr @\seebelow@ operator~() const noexcept; \end{itemdecl} \begin{itemdescr} @@ -20280,6 +20221,17 @@ A data-parallel object where the $i^\text{th}$ element is initialized to the results of applying \placeholder{op} to \tcode{operator[]($i$)} for all $i$ in the range of \range{0}{size()}. + +\pnum +\remarks +If there exists a vectorizable signed integer type \tcode{I} such that +\tcode{sizeof(I) == Bytes} is \tcode{true}, +\tcode{operator+}, \tcode{operator-}, and \tcode{operator~} +return an enabled specialization \tcode{R} of \tcode{basic_vec} such that +\tcode{R::value_type} denotes \tcode{\exposid{integer-from}} and +\tcode{R::size() == size()} is \tcode{true}. +Otherwise, +these operators are defined as deleted and their return types are unspecified. \end{itemdescr} \rSec3[simd.mask.conv]{Conversions} diff --git a/source/support.tex b/source/support.tex index c6929d58ff..e0ff828dc9 100644 --- a/source/support.tex +++ b/source/support.tex @@ -608,7 +608,7 @@ #define @\defnlibxname{cpp_lib_byte}@ 201603L // freestanding, also in \libheader{cstddef} #define @\defnlibxname{cpp_lib_byteswap}@ 202110L // freestanding, also in \libheader{bit} #define @\defnlibxname{cpp_lib_char8_t}@ 201907L - // freestanding, also in \libheader{atomic}, \libheader{filesystem}, \libheader{istream}, \libheader{limits}, \libheader{locale}, \libheader{ostream}, \libheader{string}, + // freestanding, also in \libheader{atomic}, \libheader{filesystem}, \libheader{iosfwd}, \libheader{istream}, \libheader{limits}, \libheader{locale}, \libheader{ostream}, \libheader{string}, // \libheader{string_view} #define @\defnlibxname{cpp_lib_chrono}@ 202306L // also in \libheader{chrono} #define @\defnlibxname{cpp_lib_chrono_udls}@ 201304L // also in \libheader{chrono} @@ -835,7 +835,7 @@ #define @\defnlibxname{cpp_lib_source_location}@ 201907L // freestanding, also in \libheader{source_location} #define @\defnlibxname{cpp_lib_span}@ 202311L // freestanding, also in \libheader{span} #define @\defnlibxname{cpp_lib_span_initializer_list}@ 202311L // freestanding, also in \libheader{span} -#define @\defnlibxname{cpp_lib_spanstream}@ 202106L // also in \libheader{spanstream} +#define @\defnlibxname{cpp_lib_spanstream}@ 202106L // also in \libheader{iosfwd}, \libheader{spanstream} #define @\defnlibxname{cpp_lib_ssize}@ 201902L // freestanding, also in \libheader{iterator} #define @\defnlibxname{cpp_lib_sstream_from_string_view}@ 202306L // also in \libheader{sstream} #define @\defnlibxname{cpp_lib_stacktrace}@ 202011L // also in \libheader{stacktrace} @@ -848,7 +848,7 @@ #define @\defnlibxname{cpp_lib_string_udls}@ 201304L // also in \libheader{string} #define @\defnlibxname{cpp_lib_string_view}@ 202403L // also in \libheader{string}, \libheader{string_view} #define @\defnlibxname{cpp_lib_submdspan}@ 202411L // freestanding, also in \libheader{mdspan} -#define @\defnlibxname{cpp_lib_syncbuf}@ 201803L // also in \libheader{syncstream} +#define @\defnlibxname{cpp_lib_syncbuf}@ 201803L // also in \libheader{iosfwd}, \libheader{syncstream} #define @\defnlibxname{cpp_lib_task}@ 202506L // also in \libheader{execution} #define @\defnlibxname{cpp_lib_text_encoding}@ 202306L // also in \libheader{text_encoding} #define @\defnlibxname{cpp_lib_three_way_comparison}@ 201907L // freestanding, also in \libheader{compare} @@ -6413,6 +6413,11 @@ In lieu of the default argument promotions specified in \IsoC{} 6.5.3.3, the definition in~\ref{expr.call} applies. \item +If more than one argument is present for \tcode{va_start} and +any of the second or subsequent arguments +expands to include unbalanced parentheses, or +a preprocessing token that does not convert to a token, +the program is ill-formed, no diagnostic required. The preprocessing tokens comprising the second and subsequent arguments to \tcode{va_start} (if any) are discarded. diff --git a/source/text.tex b/source/text.tex index 58d6cce5b0..3249164e90 100644 --- a/source/text.tex +++ b/source/text.tex @@ -289,7 +289,10 @@ in the \tcode{"C"} locale for the given nonzero base, as described for \tcode{strtol}, -except that no \tcode{"0x"} or \tcode{"0X"} prefix shall appear +except that +no \tcode{"0b"} or \tcode{"0B"} prefix shall appear +if the value of \tcode{base} is 2, +no \tcode{"0x"} or \tcode{"0X"} prefix shall appear if the value of \tcode{base} is 16, and except that \tcode{'-'} is the only sign that may appear, diff --git a/source/threads.tex b/source/threads.tex index db30cf641a..eafd460391 100644 --- a/source/threads.tex +++ b/source/threads.tex @@ -3778,6 +3778,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{integral-type}>} is \tcode{false}. + \pnum \expects \tcode{order} is \tcode{memory_order::relaxed}, @@ -4032,6 +4036,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{floating-point-type}>} is \tcode{false}. + \pnum \expects \tcode{order} is \tcode{memory_order::relaxed}, @@ -4267,6 +4275,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v<\placeholder{pointer-type}>} is \tcode{false}. + \pnum \mandates \tcode{remove_pointer_t<\placeholder{pointer-type}>} is a complete object type. @@ -9508,11 +9520,14 @@ \effects Transfers ownership of the lock associated with \tcode{lk} into internal storage and schedules \tcode{cond} to be notified when the current -thread exits, after all objects with thread storage duration associated with -the current thread have been destroyed. This notification is equivalent to: +thread exits. +This notification is sequenced after +all objects with thread storage duration associated with +the current thread have been destroyed and +is equivalent to: \begin{codeblock} -lk.unlock(); cond.notify_all(); +lk.unlock(); \end{codeblock} \pnum diff --git a/source/utilities.tex b/source/utilities.tex index 5e93b63c63..39b5b45412 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -3362,7 +3362,9 @@ constexpr void reset() noexcept; private: - T* @\exposidnc{val}@; // \expos + union { + remove_cv_t @\exposidnc{val}@; // \expos + }; }; template @@ -3371,19 +3373,14 @@ \end{codeblock} \pnum -An object of type \tcode{optional} at any given time -either contains a value or does not contain a value. -When an object of type \tcode{optional} -\defnx{contains a value}{contains a value!\idxcode{optional}}, -it means that an object of type \tcode{T}, referred to as the optional object's \defnx{contained value}{contained value!\idxcode{optional}}, +An instance of \tcode{optional} is said to +\defnx{contain a value}{contain a value!\idxcode{optional}} +when and only when +its member \exposid{val} is active\iref{class.union.general}; +\exposid{val} is referred to as its +\defnx{contained value}{contained value!\idxcode{optional}}. +An optional object's contained value is nested within\iref{intro.object} the optional object. -When an object of type \tcode{optional} is contextually converted to \tcode{bool}, -the conversion returns \tcode{true} if the object contains a value; -otherwise the conversion returns \tcode{false}. - -\pnum -When an object of type \tcode{optional} contains a value, -member \tcode{val} points to the contained value. \pnum A type \tcode{X} is a @@ -3434,8 +3431,8 @@ \begin{itemdescr} \pnum \effects -If \tcode{rhs} contains a value, direct-non-list-initializes the contained value -with \tcode{*rhs}. +If \tcode{rhs} contains a value, direct-non-list-initializes \exposid{val} +with \tcode{rhs.\exposid{val}}. \pnum \ensures @@ -3465,8 +3462,8 @@ \pnum \effects -If \tcode{rhs} contains a value, direct-non-list-initializes the contained value -with \tcode{*std::move(rhs)}. +If \tcode{rhs} contains a value, direct-non-list-initializes \exposid{val} +with \tcode{std::move(rhs.\exposid{val})}. \tcode{rhs.has_value()} is unchanged. \pnum @@ -3497,7 +3494,8 @@ \pnum \effects -Direct-non-list-initializes the contained value with \tcode{std::forward(args)...}. +Direct-non-list-initializes \exposid{val} +with \tcode{std::forward(args)...}. \pnum \ensures @@ -3525,7 +3523,8 @@ \pnum \effects -Direct-non-list-initializes the contained value with \tcode{il, std::forward(args)...}. +Direct-non-list-initializes \exposid{val} +with \tcode{il, std::forward(args)...}. \pnum \ensures @@ -3558,7 +3557,8 @@ \pnum \effects -Direct-non-list-initializes the contained value with \tcode{std::forward(v)}. +Direct-non-list-initializes \exposid{val} +with \tcode{std::forward(v)}. \pnum \ensures @@ -3595,7 +3595,8 @@ \pnum \effects If \tcode{rhs} contains a value, -direct-non-list-initializes the contained value with \tcode{*rhs}. +direct-non-list-initializes \exposid{val} +with \tcode{rhs.operator*()}. \pnum \ensures @@ -3630,7 +3631,8 @@ \pnum \effects If \tcode{rhs} contains a value, -direct-non-list-initializes the contained value with \tcode{*std::move(rhs)}. +direct-non-list-initializes \exposid{val} +with \tcode{std::move(rhs).operator*()}. \tcode{rhs.has_value()} is unchanged. \pnum @@ -3659,10 +3661,9 @@ \begin{itemdescr} \pnum \effects -If \tcode{is_trivially_destructible_v != true} and \tcode{*this} contains a value, calls -\begin{codeblock} -val->T::~T() -\end{codeblock} +If \tcode{is_trivially_destructible_v} is \tcode{false} +and \tcode{*this} contains a value, +calls \tcode{\exposid{val}.T::\~T()}. \pnum \remarks @@ -3679,7 +3680,7 @@ \begin{itemdescr} \pnum \effects -If \tcode{*this} contains a value, calls \tcode{val->T::\~T()} to destroy the contained value; otherwise no effect. +If \tcode{*this} contains a value, calls \tcode{\exposid{val}.T::\~T()} to destroy the contained value; otherwise no effect. \pnum \ensures @@ -3704,12 +3705,12 @@ {\tcode{*this} does not contain a value} \rowhdr{\tcode{rhs} contains a value} & -assigns \tcode{*rhs} to the contained value & -direct-non-list-initializes the contained value with \tcode{*rhs} \\ +assigns \tcode{rhs.\exposid{val}} to \exposid{val} & +direct-non-list-initializes \exposid{val} with \tcode{rhs.\exposid{val}} \\ \rowsep \rowhdr{\tcode{rhs} does not contain a value} & -destroys the contained value by calling \tcode{val->T::\~T()} & +destroys the contained value by calling \tcode{\exposid{val}.T::\~T()} & no effect \\ \end{lib2dtab2} @@ -3756,12 +3757,12 @@ {\tcode{*this} does not contain a value} \rowhdr{\tcode{rhs} contains a value} & -assigns \tcode{*std::move(rhs)} to the contained value & -direct-non-list-initializes the contained value with \tcode{*std::move(rhs)} \\ +assigns \tcode{std::move(rhs.\exposid{val})} to \exposid{val} & +direct-non-list-initializes \exposid{val} with \tcode{std::move(rhs.\exposid{val})} \\ \rowsep \rowhdr{\tcode{rhs} does not contain a value} & -destroys the contained value by calling \tcode{val->T::\~T()} & +destroys the contained value by calling \tcode{\exposid{val}.T::\~T()} & no effect \\ \end{lib2dtab2} @@ -3783,9 +3784,9 @@ \pnum If any exception is thrown, the result of the expression \tcode{this->has_value()} remains unchanged. If an exception is thrown during the call to \tcode{T}'s move constructor, -the state of \tcode{*rhs.val} is determined by the exception safety guarantee of \tcode{T}'s move constructor. +the state of \tcode{rhs.\exposid{val}} is determined by the exception safety guarantee of \tcode{T}'s move constructor. If an exception is thrown during the call to \tcode{T}'s move assignment, -the state of \tcode{*val} and \tcode{*rhs.val} is determined by the exception safety guarantee of \tcode{T}'s move assignment. +the states of \exposid{val} and \tcode{rhs.\exposid{val}} are determined by the exception safety guarantee of \tcode{T}'s move assignment. If \tcode{is_trivially_move_constructible_v \&\&} \tcode{is_trivially_move_assignable_v \&\&} \tcode{is_trivially_destructible_v} is \tcode{true}, @@ -3809,7 +3810,10 @@ \pnum \effects -If \tcode{*this} contains a value, assigns \tcode{std::forward(v)} to the contained value; otherwise direct-non-list-initializes the contained value with \tcode{std::forward(v)}. +If \tcode{*this} contains a value, +assigns \tcode{std::forward(v)} to \exposid{val}; +otherwise direct-non-list-initializes \exposid{val} +with \tcode{std::forward(v)}. \pnum \ensures @@ -3821,7 +3825,9 @@ \pnum \remarks -If any exception is thrown, the result of the expression \tcode{this->has_value()} remains unchanged. If an exception is thrown during the call to \tcode{T}'s constructor, the state of \tcode{v} is determined by the exception safety guarantee of \tcode{T}'s constructor. If an exception is thrown during the call to \tcode{T}'s assignment, the state of \tcode{*val} and \tcode{v} is determined by the exception safety guarantee of \tcode{T}'s assignment. +If any exception is thrown, the result of the expression \tcode{this->has_value()} remains unchanged. If an exception is thrown during the call to \tcode{T}'s constructor, the state of \tcode{v} is determined by the exception safety guarantee of \tcode{T}'s constructor. If an exception is thrown during the call to \tcode{T}'s assignment, +the states of \exposid{val} and \tcode{v} are +determined by the exception safety guarantee of \tcode{T}'s assignment. \end{itemdescr} \indexlibrarymember{operator=}{optional}% @@ -3850,12 +3856,12 @@ {\tcode{*this} does not contain a value} \rowhdr{\tcode{rhs} contains a value} & -assigns \tcode{*rhs} to the contained value & -direct-non-list-initializes the contained value with \tcode{*rhs} \\ +assigns \tcode{rhs.operator*()} to \exposid{val} & +direct-non-list-initializes \exposid{val} with \tcode{rhs.operator*()} \\ \rowsep \rowhdr{\tcode{rhs} does not contain a value} & -destroys the contained value by calling \tcode{val->T::\~T()} & +destroys the contained value by calling \tcode{\exposid{val}.T::\~T()} & no effect \\ \end{lib2dtab2} @@ -3872,10 +3878,10 @@ If any exception is thrown, the result of the expression \tcode{this->has_value()} remains unchanged. If an exception is thrown during the call to \tcode{T}'s constructor, -the state of \tcode{*rhs.val} is determined by +the state of \tcode{rhs.\exposid{val}} is determined by the exception safety guarantee of \tcode{T}'s constructor. If an exception is thrown during the call to \tcode{T}'s assignment, -the state of \tcode{*val} and \tcode{*rhs.val} is determined by +the states of \exposid{val} and \tcode{rhs.\exposid{val}} are determined by the exception safety guarantee of \tcode{T}'s assignment. \end{itemdescr} @@ -3906,12 +3912,12 @@ {\tcode{*this} does not contain a value} \rowhdr{\tcode{rhs} contains a value} & -assigns \tcode{*std::move(rhs)} to the contained value & -direct-non-list-initializes the contained value with \tcode{*std::move(rhs)} \\ +assigns \tcode{std::move(rhs).op\-erator*()} to \exposid{val} & +direct-non-list-initializes \exposid{val} with \tcode{std::move(rhs).opera\-tor*()} \\ \rowsep \rowhdr{\tcode{rhs} does not contain a value} & -destroys the contained value by calling \tcode{val->T::\~T()} & +destroys the contained value by calling \tcode{\exposid{val}.T::\~T()} & no effect \\ \end{lib2dtab2} @@ -3928,10 +3934,10 @@ If any exception is thrown, the result of the expression \tcode{this->has_value()} remains unchanged. If an exception is thrown during the call to \tcode{T}'s constructor, -the state of \tcode{*rhs.val} is determined by +the state of \tcode{rhs.\exposid{val}} is determined by the exception safety guarantee of \tcode{T}'s constructor. If an exception is thrown during the call to \tcode{T}'s assignment, -the state of \tcode{*val} and \tcode{*rhs.val} is determined by +the states of \exposid{val} and \tcode{rhs.\exposid{val}} are determined by the exception safety guarantee of \tcode{T}'s assignment. \end{itemdescr} @@ -3947,8 +3953,8 @@ \pnum \effects -Calls \tcode{*this = nullopt}. Then direct-non-list-initializes the contained value -with \tcode{std::forward\brk{}(args)...}. +Calls \tcode{*this = nullopt}. Then direct-non-list-initializes \exposid{val} +with \tcode{std::forward(args\brk{})...}. \pnum \ensures @@ -3956,7 +3962,7 @@ \pnum \returns -A reference to the new contained value. +\exposid{val}. \pnum \throws @@ -3964,7 +3970,9 @@ \pnum \remarks -If an exception is thrown during the call to \tcode{T}'s constructor, \tcode{*this} does not contain a value, and the previous \tcode{*val} (if any) has been destroyed. +If an exception is thrown during the call to \tcode{T}'s constructor, +\tcode{*this} does not contain a value, and +the previous \exposid{val} (if any) has been destroyed. \end{itemdescr} \indexlibrarymember{emplace}{optional}% @@ -3979,8 +3987,8 @@ \pnum \effects -Calls \tcode{*this = nullopt}. Then direct-non-list-initializes the contained value with -\tcode{il, std::\brk{}forward(args)...}. +Calls \tcode{*this = nullopt}. Then direct-non-list-initializes \exposid{val} with +\tcode{il, std::forward(\brk{}args)...}. \pnum \ensures @@ -3988,7 +3996,7 @@ \pnum \returns -A reference to the new contained value. +\exposid{val}. \pnum \throws @@ -3996,7 +4004,9 @@ \pnum \remarks -If an exception is thrown during the call to \tcode{T}'s constructor, \tcode{*this} does not contain a value, and the previous \tcode{*val} (if any) has been destroyed. +If an exception is thrown during the call to \tcode{T}'s constructor, +\tcode{*this} does not contain a value, and +the previous \exposid{val} (if any) has been destroyed. \end{itemdescr} \rSec3[optional.swap]{Swap} @@ -4023,17 +4033,17 @@ {\tcode{*this} does not contain a value} \rowhdr{\tcode{rhs} contains a value} & -calls \tcode{swap(*(*this), *rhs)} & -direct-non-list-initializes the contained value of \tcode{*this} -with \tcode{std::move(*rhs)}, -followed by \tcode{rhs.val->T::\~T()}; +calls \tcode{swap(\exposid{val}, rhs.\exposid{val})} & +direct-non-list-initializes \exposid{val} +with \tcode{std::move(rhs.\exposid{val})}, +followed by \tcode{rhs.\exposid{val}.T::\~T()}; postcondition is that \tcode{*this} contains a value and \tcode{rhs} does not contain a value \\ \rowsep \rowhdr{\tcode{rhs} does not contain a value} & -direct-non-list-initializes the contained value of \tcode{rhs} -with \tcode{std::move(*(*this))}, -followed by \tcode{val->T::\~T()}; +direct-non-list-initializes \tcode{rhs.\exposid{val}} +with \tcode{std::move(\exposid{val})}, +followed by \tcode{\exposid{val}.T::\~T()}; postcondition is that \tcode{*this} does not contain a value and \tcode{rhs} contains a value & no effect \\ \end{lib2dtab2} @@ -4052,9 +4062,9 @@ \pnum If any exception is thrown, the results of the expressions \tcode{this->has_value()} and \tcode{rhs.has_value()} remain unchanged. If an exception is thrown during the call to function \tcode{swap}, -the state of \tcode{*val} and \tcode{*rhs.val} is determined by the exception safety guarantee of \tcode{swap} for lvalues of \tcode{T}. +the states of \exposid{val} and \tcode{rhs.\exposid{val}} are determined by the exception safety guarantee of \tcode{swap} for lvalues of \tcode{T}. If an exception is thrown during the call to \tcode{T}'s move constructor, -the state of \tcode{*val} and \tcode{*rhs.val} is determined by the exception safety guarantee of \tcode{T}'s move constructor. +the states of \exposid{val} and \tcode{rhs.\exposid{val}} are determined by the exception safety guarantee of \tcode{T}'s move constructor. \end{itemdescr} \rSec3[optional.iterators]{Iterator support} @@ -4125,7 +4135,7 @@ \pnum \returns -\tcode{val}. +\tcode{addressof(\exposid{val})}. \pnum \remarks @@ -4145,7 +4155,7 @@ \pnum \returns -\tcode{*val}. +\exposid{val}. \pnum \remarks @@ -4165,7 +4175,7 @@ \pnum \effects -Equivalent to: \tcode{return std::move(*val);} +Equivalent to: \tcode{return std::move(\exposid{val});} \end{itemdescr} \indexlibrarymember{operator bool}{optional}% @@ -4209,7 +4219,7 @@ \effects Equivalent to: \begin{codeblock} -return has_value() ? *val : throw bad_optional_access(); +return has_value() ? @\exposid{val}@ : throw bad_optional_access(); \end{codeblock} \end{itemdescr} @@ -4225,7 +4235,7 @@ \effects Equivalent to: \begin{codeblock} -return has_value() ? std::move(*val) : throw bad_optional_access(); +return has_value() ? std::move(@\exposid{val}@) : throw bad_optional_access(); \end{codeblock} \end{itemdescr} @@ -4243,7 +4253,7 @@ \effects Equivalent to: \begin{codeblock} -return has_value() ? **this : static_cast(std::forward(v)); +return has_value() ? @\exposid{val}@ : static_cast(std::forward(v)); \end{codeblock} \end{itemdescr} @@ -4261,7 +4271,7 @@ \effects Equivalent to: \begin{codeblock} -return has_value() ? std::move(**this) : static_cast(std::forward(v)); +return has_value() ? std::move(@\exposid{val}@) : static_cast(std::forward(v)); \end{codeblock} \end{itemdescr} @@ -4275,7 +4285,7 @@ \begin{itemdescr} \pnum -Let \tcode{U} be \tcode{invoke_result_t}. +Let \tcode{U} be \tcode{invoke_result_t}. \pnum \mandates @@ -4286,7 +4296,7 @@ Equivalent to: \begin{codeblock} if (*this) { - return invoke(std::forward(f), *@\exposid{val}@); + return invoke(std::forward(f), @\exposid{val}@); } else { return remove_cvref_t(); } @@ -4301,7 +4311,7 @@ \begin{itemdescr} \pnum -Let \tcode{U} be \tcode{invoke_result_t}. +Let \tcode{U} be \tcode{invoke_result_t}. \pnum \mandates @@ -4312,7 +4322,7 @@ Equivalent to: \begin{codeblock} if (*this) { - return invoke(std::forward(f), std::move(*@\exposid{val}@)); + return invoke(std::forward(f), std::move(@\exposid{val}@)); } else { return remove_cvref_t(); } @@ -4327,14 +4337,14 @@ \begin{itemdescr} \pnum -Let \tcode{U} be \tcode{remove_cv_t>}. +Let \tcode{U} be \tcode{remove_cv_t>}. \pnum \mandates \tcode{U} is a valid contained type for \tcode{optional}. The declaration \begin{codeblock} -U u(invoke(std::forward(f), *@\exposid{val}@)); +U u(invoke(std::forward(f), @\exposid{val}@)); \end{codeblock} is well-formed for some invented variable \tcode{u}. \begin{note} @@ -4345,7 +4355,7 @@ \returns If \tcode{*this} contains a value, an \tcode{optional} object whose contained value is direct-non-list-initialized with -\tcode{invoke(std::forward(f), *\exposid{val})}; +\tcode{invoke(std::forward(f), \exposid{val})}; otherwise, \tcode{optional()}. \end{itemdescr} @@ -4358,14 +4368,14 @@ \begin{itemdescr} \pnum Let \tcode{U} be -\tcode{remove_cv_t>}. +\tcode{remove_cv_t>}. \pnum \mandates \tcode{U} is a valid contained type for \tcode{optional}. The declaration \begin{codeblock} -U u(invoke(std::forward(f), std::move(*@\exposid{val}@))); +U u(invoke(std::forward(f), std::move(@\exposid{val}@))); \end{codeblock} is well-formed for some invented variable \tcode{u}. \begin{note} @@ -4376,7 +4386,7 @@ \returns If \tcode{*this} contains a value, an \tcode{optional} object whose contained value is direct-non-list-initialized with -\tcode{invoke(std::forward(f), std::move(*\exposid{val}))}; +\tcode{invoke(std::forward(f), std::move(\exposid{val}))}; otherwise, \tcode{optional()}. \end{itemdescr} @@ -4444,7 +4454,7 @@ \begin{itemdescr} \pnum \effects -If \tcode{*this} contains a value, calls \tcode{val->T::\~T()} to destroy the contained value; +If \tcode{*this} contains a value, calls \tcode{\exposid{val}.T::\~T()} to destroy the contained value; otherwise no effect. \pnum @@ -4460,8 +4470,9 @@ template class optional { public: - using value_type = T; - using iterator = @\impdefnc@; // see~\ref{optional.ref.iterators} + using value_type = T; + using iterator = @\impdefnc@; // present only if \tcode{T} is an object type other than an array + // of unknown bound; see~\ref{optional.ref.iterators} public: // \ref{optional.ref.ctor}, constructors @@ -4494,8 +4505,8 @@ constexpr void swap(optional& rhs) noexcept; // \ref{optional.ref.iterators}, iterator support - constexpr iterator begin() const noexcept; - constexpr iterator end() const noexcept; + constexpr auto begin() const noexcept; + constexpr auto end() const noexcept; // \ref{optional.ref.observe}, observers constexpr T* operator->() const noexcept; @@ -4607,7 +4618,7 @@ \effects Equivalent to: \begin{codeblock} -if (rhs.has_value()) @\exposid{convert-ref-init-val}@(*rhs); +if (rhs.has_value()) @\exposid{convert-ref-init-val}@(rhs.operator*()); \end{codeblock} \pnum @@ -4638,7 +4649,7 @@ \effects Equivalent to: \begin{codeblock} -if (rhs.has_value()) @\exposid{convert-ref-init-val}@(*rhs); +if (rhs.has_value()) @\exposid{convert-ref-init-val}@(rhs.operator*()); \end{codeblock} \pnum @@ -4669,7 +4680,7 @@ \effects Equivalent to: \begin{codeblock} -if (rhs.has_value()) @\exposid{convert-ref-init-val}@(*std::move(rhs)); +if (rhs.has_value()) @\exposid{convert-ref-init-val}@(std::move(rhs).operator*()); \end{codeblock} \pnum @@ -4700,7 +4711,7 @@ \effects Equivalent to: \begin{codeblock} -if (rhs.has_value()) @\exposid{convert-ref-init-val}@(*std::move(rhs)); +if (rhs.has_value()) @\exposid{convert-ref-init-val}@(std::move(rhs).operator*()); \end{codeblock} \pnum @@ -4763,13 +4774,14 @@ \begin{itemdescr} \pnum \effects -Equivalent to: \tcode{swap(\exposid{val}, rhs.\exposid{val})}. +Equivalent to: \tcode{std::swap(\exposid{val}, rhs.\exposid{val})}. \end{itemdescr} \rSec3[optional.ref.iterators]{Iterator support} \begin{itemdecl} -using iterator = @\impdef@; +using iterator = @\impdefnc@; // present only if \tcode{T} is an object type other than an array + // of unknown bound \end{itemdecl} \begin{itemdescr} @@ -4787,22 +4799,31 @@ \end{itemdescr} \begin{itemdecl} -constexpr iterator begin() const noexcept; +constexpr auto begin() const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{T} is an object type other than an array of unknown bound. + \pnum \returns - If \tcode{has_value()} is \tcode{true}, - an iterator referring to \tcode{*\exposid{val}}. - Otherwise, a past-the-end iterator value. + An object \tcode{i} of type \tcode{iterator}, such that + \tcode{i} is an iterator referring to \tcode{*\exposid{val}} + if \tcode{has_value()} is \tcode{true}, and + a past-the-end iterator value otherwise. \end{itemdescr} \begin{itemdecl} -constexpr iterator end() const noexcept; +constexpr auto end() const noexcept; \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{T} is an object type other than an array of unknown bound. + \pnum \returns \tcode{begin() + has_value()}. @@ -4877,6 +4898,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\constraints +\tcode{T} is a non-array object type. + \pnum Let \tcode{X} be \tcode{remove_cv_t}. @@ -4890,6 +4915,14 @@ \begin{codeblock} return has_value() ? *@\exposid{val}@ : static_cast(std::forward(u)); \end{codeblock} + +\pnum +\remarks +The return type is unspecified if +\tcode{T} is an array type or a non-object type. +\begin{note} +This is to avoid the declaration being ill-formed. +\end{note} \end{itemdescr} \rSec3[optional.ref.monadic]{Monadic operations}