This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Resolved status.
<future> still has type-erased allocators in promiseSection: 32.10.6 [futures.promise] Status: Resolved Submitter: Billy O'Neal III Opened: 2017-07-16 Last modified: 2025-06-23
Priority: 2
View all other issues in [futures.promise].
View all issues with Resolved status.
Discussion:
In Toronto Saturday afternoon LWG discussed LWG 2976(i) which finishes the job of removing allocator
support from packaged_task. LWG confirmed that, despite the removal of packaged_task allocators
"because it looks like std::function" was incorrect, they wanted to keep the allocator removals anyway,
in large part due to this resolution being a response to an NB comment.
<future>, namely, in promise.
This change also resolves potential implementation divergence on whether allocator::construct is intended
to be used on elements constructed in the shared state, and allows the emplace-construction-in-future paper,
P0319, to be implemented without potential problems there.
[28-Nov-2017 Mailing list discussion - set priority to P2]
Lots of people on the ML feel strongly about this; the suggestion was made that a paper would be welcomed laying out the rationale for removing allocator support here (and in other places).
[2018-1-26 issues processing telecon]
Status to 'Open'; Billy to write a paper.
[2019-06-03]
Jonathan observes that this resolution conflicts with 2095(i).
[Varna 2023-06-13; Change status to "LEWG"]
Previous resolution [SUPERSEDED]:
This resolution is relative to N4659.
Edit 32.10.6 [futures.promise], class template
promisesynopsis, as indicated:template<class R> class promise { public: promise();[…]template <class Allocator> promise(allocator_arg_t, const Allocator& a);[…] }; template <class R> void swap(promise<R>& x, promise<R>& y) noexcept;template <class R, class Alloc> struct uses_allocator<promise<R>, Alloc>;template <class R, class Alloc> struct uses_allocator<promise<R>, Alloc> : true_type { };
-3- Requires:Allocshall be an Allocator (16.4.4.6 [allocator.requirements]).promise();template <class Allocator> promise(allocator_arg_t, const Allocator& a);-4- Effects: constructs a
promiseobject and a shared state.The second constructor uses the allocator a to allocate memory for the shared state.
[2024-09-19; Jonathan provides improved wording]
In July 2023 LEWG considered this and LWG issue 2095(i)
and requested a new proposed resolution that kept the existing constructor
(which is useful for controlling how the shared state is allocated)
but removed the uses_allocator specialization that makes promise
incorrectly claim to be allocator-aware.
Some of the rationale in P2787R1 is applicable here too.
Without the uses_allocator specialization, there's no reason to provide
an allocator-extended move constructor, resolving issue 2095(i).
And if we're going to continue supporting std::promise construction
with an allocator, we could restore that for std::packaged_task too.
That was removed by issue 2921(i), but issue 2976(i)
argues that there was no good reason to do that. Removing uses_allocator
for packaged_task would have made sense (as proposed below for promise)
but 2921 didn't do that (which is why 2976 was needed).
We can restore the packaged_task constructor that takes an allocator,
and just not restore the uses_allocator specialization that implies
it should be fully allocator-aware.
Finally, if we restore that packaged_task constructor then we need to
fix reset() as discussed in issue 2245(i).
In summary:
promise.uses_allocator specialization for promise.packaged_task.uses_allocator specialization for packaged_task.packaged_task::reset() to deal with allocators.[Wrocław 2024-11-18; LEWG would prefer a paper for this]
[2025-06-21 Status changed: LEWG → Resolved.]
Resolved by adoption of P3503R3 in Sofia.Proposed resolution:
This wording is relative to N4988.
Modify 32.10.6 [futures.promise] as indicated:
[…]template <class R, class Alloc> struct uses_allocator<promise<R>, Alloc>;template <class R, class Alloc> struct uses_allocator<promise<R>, Alloc> : true_type { };
-4- Preconditions:Allocmeets the Cpp17Allocator (16.4.4.6.1 [allocator.requirements.general]).
Modify 32.10.10.1 [futures.task.general] as indicated:
template<class R, class... ArgTypes>
class packaged_task<R(ArgTypes...)> {
public:
// construction and destruction
packaged_task() noexcept;
template<class F>
explicit packaged_task(F&& f);
~packaged_task();
Modify 32.10.10.2 [futures.task.members] as indicated:
template<class F> explicit packaged_task(F&& f);
[Drafting note: Uses ofstd::allocator<int>andstd::allocator<unspecified>are not observable so this constructor can be implemented without delegating to the other constructor and without usingstd::allocator.]-2- Constraints:
remove_cvref_t<F>is not the same type aspackaged_task<R(ArgTypes...)>.-3- Mandates:
is_invocable_r_v<R, F&, ArgTypes...>istrue.[Drafting note: Issue 4154(i) alters these Mandates: and Effects: but the two edits should combine cleanly.]-4- Preconditions: Invoking a copy of
fbehaves the same as invokingf.-5- Effects: Creates a shared state and initializes the object's stored task with
std::forward<F>(f).-6- Throws:
Any exceptions thrown by the copy or move constructor off, or bad_alloc if memory for the internal data structures cannot be allocated.…
void reset();-26- Effects:
As if*this = packaged_task( std::move(f));wherefis the task stored in*this.[Note 2: This constructs a new shared state for
*this. The old state is abandoned (32.10.5 [futures.state]). — end note]-27- Throws:
(27.1) — bad_alloc if memory for the new shared state cannot be allocated.- (27.2) — Any exception thrown by the
move constructor of the task stored in the shared state.- (27.3) —
future_errorwith an error condition ofno_stateif*thishas no shared state.