/usr/include/c++/11/bits/uses_allocator_args.h:78:29: error: static assertion failed: construction with an allocator must be possible if uses_allocator is true
78 | static_assert(is_constructible_v<_Tp, _Args..., const _Alloc&>,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/11/bits/uses_allocator_args.h:78:29: note: ‘std::is_constructible_v<std::promise<int>, const std::allocator_arg_t&, std::pmr::polymorphic_allocator<char>&, const std::pmr::polymorphic_allocator<char>&>’ evaluates to false
Note that the allocator is appearing twice in the arguments to the std::promise<int> constructor!
Indeed, this also fails to compile in the same way:
#include <future>
#include <memory_resource>
int main() {
std::pmr::synchronized_pool_resource memory_pool;
auto const promise = std::allocate_shared<std::promise<int>>(std::pmr::polymorphic_allocator<>{&memory_pool}, std::allocator_arg, std::pmr::polymorphic_allocator<>{&memory_pool});
return 0;
}
This appears to be because std::allocate_shared uses the allocator's construct method to create the object held by the shared pointer, and std::pmr::polymorphic_allocator does uses-allocator construction, which means it forwards the top-level (shared pointer) allocator to the constructor of any type T that defines std::uses_allocator<T>::value to be true (which it is for std::promise).
The correct way to call std::allocate_shared with these types is:
#include <future>
#include <memory_resource>
int main() {
std::pmr::synchronized_pool_resource memory_pool;
auto const promise = std::allocate_shared<std::promise<int>>(std::pmr::polymorphic_allocator<>{&memory_pool});
return 0;
}
and let the machinery of the standard library figure out how to pass the allocator on to std::promise<int>.
I suspect the fix is a bit more complex than that, however - I'm not sure that there's a good way to detect whether the allocator does uses-allocator construction or not, and simply dropping these arguments may cause existing code using custom allocators to silently start allocating the promise's shared state using global new.
This code does not compile (in C++20 mode; the same effect can be seen with
std::pmr::polymorphic_allocator<void>
in C++17):The key part of the error output is this:
Note that the allocator is appearing twice in the arguments to the
std::promise<int>
constructor!The issue is this line in
impl/use_future.hpp
:Indeed, this also fails to compile in the same way:
This appears to be because
std::allocate_shared
uses the allocator'sconstruct
method to create the object held by the shared pointer, andstd::pmr::polymorphic_allocator
does uses-allocator construction, which means it forwards the top-level (shared pointer) allocator to the constructor of any typeT
that definesstd::uses_allocator<T>::value
to betrue
(which it is forstd::promise
).The correct way to call
std::allocate_shared
with these types is:and let the machinery of the standard library figure out how to pass the allocator on to
std::promise<int>
.I suspect the fix is a bit more complex than that, however - I'm not sure that there's a good way to detect whether the allocator does uses-allocator construction or not, and simply dropping these arguments may cause existing code using custom allocators to silently start allocating the promise's shared state using global
new
.