From 7409f3fc79968357e396dd06e589cf0bee294fec Mon Sep 17 00:00:00 2001 From: Eisenwave Date: Sat, 4 Apr 2026 20:00:16 +0200 Subject: [PATCH 1/2] =?UTF-8?q?P3980R1=20Task=E2=80=99s=20Allocator=20Use?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes NB US 254-385, US 253-386, US 255-384, and US 261-391 (C++26 CD). --- source/exec.tex | 89 +++++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 44 deletions(-) diff --git a/source/exec.tex b/source/exec.tex index 4455a1c991..80cb0f9aea 100644 --- a/source/exec.tex +++ b/source/exec.tex @@ -7331,6 +7331,13 @@ @\exposid{state}@ connect(Rcvr&& recv) &&; \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +At least one of the expressions +\tcode{allocator_type(get_allocator(get_env(rcvr)))} and +\tcode{allocator_type()} +is well-formed. + \pnum \expects \tcode{bool(\exposid{handle})} is \tcode{true}. @@ -7458,9 +7465,6 @@ template class task::promise_type { public: - template - promise_type(const Args&... args); - task get_return_object() noexcept; static constexpr suspend_always @\libmember{initial_suspend}{task::promise_type}@() noexcept { return {}; } @@ -7483,15 +7487,17 @@ @\unspec@ get_env() const noexcept; - template - void* operator new(size_t size, Args&&... args); + void* operator new(size_t size); + template + void* operator new(size_t size, allocator_arg_t, Alloc alloc, Args&&...); + template + void* operator new(size_t size, const This&, allocator_arg_t, Alloc alloc, Args&&...); void operator delete(void* pointer, size_t size) noexcept; private: using @\exposidnc{error-variant}@ = @\seebelownc@; // \expos - allocator_type @\exposidnc{alloc}@; // \expos stop_source_type @\exposidnc{source}@; // \expos stop_token_type @\exposidnc{token}@; // \expos optional @\exposidnc{result}@; // \expos; present only if \tcode{is_void_v} is \tcode{false} @@ -7519,25 +7525,6 @@ \tcode{execution::completion_signatures} denoted by \tcode{error_types}. -\indexlibraryctor{task::promise_type}% -\begin{itemdecl} -template - promise_type(const Args&... args); -\end{itemdecl} -\begin{itemdescr} -\pnum -\mandates -The first parameter of type \tcode{allocator_arg_t} (if any) is not -the last parameter. - -\pnum -\effects -If \tcode{Args} contains an element of type \tcode{allocator_arg_t} -then \exposid{alloc} is initialized with the corresponding next -element of \tcode{args}. -Otherwise, \exposid{alloc} is initialized with \tcode{allocator_type()}. -\end{itemdescr} - \indexlibrarymember{get_return_object}{task::promise_type}% \begin{itemdecl} task get_return_object() noexcept; @@ -7679,10 +7666,19 @@ \returns An object \tcode{env} such that queries are forwarded as follows: \begin{itemize} -\item \tcode{env.query(get_scheduler)} returns \tcode{scheduler_type(\exposid{SCHED}(*this))}. -\item \tcode{env.query(get_allocator)} returns \exposid{alloc}. -\item \tcode{env.query(get_stop_token)} returns \exposid{token}. -\item For any other query \tcode{q} and arguments \tcode{a...} a +\item +\tcode{env.query(get_scheduler)} returns +\tcode{scheduler_type(\exposid{SCHED}(*this))}. +\item +\tcode{env.query(get_allocator)} returns +\tcode{allocator_type(get_allocator(get_env(\exposid{RCVR}(*this))\brk{}))} +if this expression is well-formed and +\tcode{allocator_type()} otherwise. +\item +\tcode{env.query(get_stop_token)} +returns \exposid{token}. +\item +For any other query \tcode{q} and arguments \tcode{a...} a call to \tcode{env.query(q, a...)} returns \tcode{\exposid{STATE}(*this)}. \tcode{environment.query(q, a...)} if this expression is well-formed and \tcode{forwarding_query(q)} is well-formed and is \tcode{true}. @@ -7692,28 +7688,33 @@ \indexlibrarymember{operator new}{task::promise_type}% \begin{itemdecl} -template - void* operator new(size_t size, const Args&... args); +void* operator new(size_t size); \end{itemdecl} + \begin{itemdescr} \pnum -If there is no parameter with type \tcode{allocator_arg_t} then let -\tcode{alloc} be \tcode{allocator_type()}. -Otherwise, let \tcode{arg_next} be the parameter -following the first \tcode{allocator_arg_t} parameter, -and let \tcode{alloc} be \tcode{allocator_type(arg_next)}. -Let \tcode{PAlloc} be \tcode{allocator_traits::template -rebind_alloc}, where \tcode{U} is an unspecified type +\effects +Equivalent to: +\tcode{return operator new(size, allocator_arg, allocator_type());} +\end{itemdescr} + +\indexlibrarymember{operator new}{task::promise_type}% +\begin{itemdecl} +template + void* operator new(size_t size, allocator_arg_t, Alloc alloc, const Args&...); +template + void* operator new(size_t size, const This&, allocator_arg_t, Alloc alloc, Args&&...); +\end{itemdecl} +\begin{itemdescr} +\pnum +Let \tcode{PAlloc} be +\tcode{allocator_traits::template rebind_alloc}, +where \tcode{U} is an unspecified type whose size and alignment are both \mname{STDCPP_DEFAULT_NEW_ALIGNMENT}. \pnum \mandates -\begin{itemize} -\item The first parameter of type \tcode{allocator_arg_t} (if any) is not the last parameter. -\item \tcode{allocator_type(arg_next)} is a valid expression if there is a parameter -of type \tcode{allocator_arg_t}. -\item \tcode{allocator_traits::pointer} is a pointer type. -\end{itemize} +\tcode{allocator_traits::pointer} is a pointer type. \pnum \effects From 04c21fa3160cd1c8030f71d3d71526f5dd24750a Mon Sep 17 00:00:00 2001 From: Eisenwave Date: Sat, 4 Apr 2026 20:17:42 +0200 Subject: [PATCH 2/2] [task.promise] Replace const Args&... with Args&&... P3980R1 adds "Args&&..." signatures, but is missing the markup that would remove the existing "const Args&...". "const Args&..." is inconsistent with the synopsis. --- source/exec.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/exec.tex b/source/exec.tex index 80cb0f9aea..1f5af1928c 100644 --- a/source/exec.tex +++ b/source/exec.tex @@ -7701,7 +7701,7 @@ \indexlibrarymember{operator new}{task::promise_type}% \begin{itemdecl} template - void* operator new(size_t size, allocator_arg_t, Alloc alloc, const Args&...); + void* operator new(size_t size, allocator_arg_t, Alloc alloc, Args&&...); template void* operator new(size_t size, const This&, allocator_arg_t, Alloc alloc, Args&&...); \end{itemdecl}