promise and packaged_task missing constructors needed for uses-allocator constructionSection: 32.10.6 [futures.promise], 32.10.10 [futures.task] Status: Resolved Submitter: Jonathan Wakely Opened: 2011-11-01 Last modified: 2025-06-23
Priority: 4
View all other issues in [futures.promise].
View all issues with Resolved status.
Discussion:
This example is ill-formed according to C++11 because uses_allocator<promise<R>, A>::value is true, but
is_constructible<promise<R>, A, promise<R>&&>::value is false. Similarly for packaged_task.
#include <future>
#include <memory>
#include <tuple>
using namespace std;
typedef packaged_task<void()> task;
typedef promise<void> prom;
allocator<task> a;
tuple<task, prom> t1{ allocator_arg, a };
tuple<task, prom> t2{ allocator_arg, a, task{}, prom{} };
[2012, Portland]
This is an allocator issue, and should be dealt with directly by LWG.
[2013-03-06]
Jonathan suggests to make the new constructors non-explicit and makes some representational improvements.
[2013-09 Chicago]
Move to deferred.
This issue has much in common with similar problems with std::function that are being addressed
by the polymorphic allocators proposal currently under evaluation in LEWG. Defer further discussion on
this topic until the final outcome of that paper and its proposed resolution is known.
[2014-02-20 Re-open Deferred issues as Priority 4]
[2016-08 Chicago]
Fri PM: Send to LEWG - and this also applies to function in LFTS.
[2019-06-03 Jonathan Wakely provides updated wording]
Jonathan updates wording post-2976 and observes that this resolution conflicts with 3003.
Previous resolution [SUPERSEDED]:
[This wording is relative to the FDIS.]
Add to 32.10.6 [futures.promise], class template
promisesynopsis, as indicated:namespace std { template <class R> class promise { public: promise(); template <class Allocator> promise(allocator_arg_t, const Allocator& a); template <class Allocator> promise(allocator_arg_t, const Allocator& a, promise&& rhs) noexcept; promise(promise&& rhs) noexcept; promise(const promise& rhs) = delete; ~promise(); […] }; […] }Change 32.10.6 [futures.promise] as indicated:
promise(promise&& rhs) noexcept; template <class Allocator> promise(allocator_arg_t, const Allocator& a, promise&& rhs) noexcept;-5- Effects: constructs a new
-6- Postcondition:promiseobject and transfers ownership of the shared state ofrhs(if any) to the newly-constructed object.rhshas no shared state. -?- [Note:ais not used — end note]Add to 32.10.10 [futures.task], class template
packaged_tasksynopsis, as indicated:namespace std { template<class> class packaged_task; // undefined template<class R, class... ArgTypes> class packaged_task<R(ArgTypes...)> { public: // construction and destruction packaged_task() noexcept; template <class Allocator> packaged_task(allocator_arg_t, const Allocator& a) noexcept; template <class F> explicit packaged_task(F&& f); template <class F, class Allocator> explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f); ~packaged_task(); // no copy packaged_task(const packaged_task&) = delete; template<class Allocator> packaged_task(allocator_arg_t, const Allocator& a, const packaged_task&) = delete; packaged_task& operator=(const packaged_task&) = delete; // move support packaged_task(packaged_task&& rhs) noexcept; template <class Allocator> packaged_task(allocator_arg_t, const Allocator& a, packaged_task&& rhs) noexcept; packaged_task& operator=(packaged_task&& rhs) noexcept; void swap(packaged_task& other) noexcept; […] }; […] }Change 32.10.10.2 [futures.task.members] as indicated:
packaged_task() noexcept; template <class Allocator> packaged_task(allocator_arg_t, const Allocator& a) noexcept;-1- Effects: constructs a
-?- [Note:packaged_taskobject with no shared state and no stored task.ais not used — end note][…]
packaged_task(packaged_task&& rhs) noexcept; template <class Allocator> packaged_task(allocator_arg_t, const Allocator& a, packaged_task&& rhs) noexcept;-5- Effects: constructs a new
-6- Postcondition:packaged_taskobject and transfers ownership ofrhs's shared state to*this, leavingrhswith no shared state. Moves the stored task fromrhsto*this.rhshas no shared state. -?- [Note:ais not used — end note]
[2025-06-21 Status changed: LEWG → Resolved.]
Resolved by adoption of P3503R3 in Sofia.Proposed resolution:
[This wording is relative to N4810.]
Add to 32.10.6 [futures.promise], class template promise synopsis,
as indicated:
namespace std {
template <class R>
class promise {
public:
promise();
template <class Allocator>
promise(allocator_arg_t, const Allocator& a);
template <class Allocator>
promise(allocator_arg_t, const Allocator& a, promise&& rhs) noexcept;
promise(promise&& rhs) noexcept;
promise(const promise& rhs) = delete;
~promise();
[…]
};
[…]
}
Change 32.10.6 [futures.promise] as indicated:
promise(promise&& rhs) noexcept; template <class Allocator> promise(allocator_arg_t, const Allocator& a, promise&& rhs) noexcept;-5- Effects: constructs a new
-6- Postcondition:promiseobject and transfers ownership of the shared state ofrhs(if any) to the newly-constructed object.rhshas no shared state. -?- [Note:ais not used — end note]