I am attempting to create shared pointers with a std::pmr::monotonic_buffer_resource
, and I cannot make it compile. What am I missing?
#include <memory>
#include <memory_resource>
int main() {
char buffer[100];
std::pmr::monotonic_buffer_resource mbr(buffer, 100);
std::shared_ptr<double> sp = std::allocate_shared<double>(mbr);
}
In file included from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/ext/alloc_traits.h:34, from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_uninitialized.h:67, from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/memory:66, from <source>:1: /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/alloc_traits.h: In substitution of 'template<class _Alloc, class _Up> using __alloc_rebind = typename std::__allocator_traits_base::__rebind<_Alloc, _Up>::type [with _Alloc = std::pmr::monotonic_buffer_resource; _Up = std::_Sp_counted_ptr_inplace<double, std::pmr::monotonic_buffer_resource, __gnu_cxx::_S_atomic>]': /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr_base.h:542:13: required from 'class std::_Sp_counted_ptr_inplace<double, std::pmr::monotonic_buffer_resource, __gnu_cxx::_S_atomic>' /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr_base.h:679:43: required from 'std::__shared_count<_Lp>::__shared_count(_Tp*&, std::_Sp_alloc_shared_tag<_Alloc>, _Args&& ...) [with _Tp = double; _Alloc = std::pmr::monotonic_buffer_resource; _Args = {}; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]' /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr_base.h:1371:71: required from 'std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::_Sp_alloc_shared_tag<_Tp>, _Args&& ...) [with _Alloc = std::pmr::monotonic_buffer_resource; _Args = {}; _Tp = double; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]' /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr.h:408:59: required from 'std::shared_ptr<_Tp>::shared_ptr(std::_Sp_alloc_shared_tag<_Tp>, _Args&& ...) [with _Alloc = std::pmr::monotonic_buffer_resource; _Args = {}; _Tp = double]' /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr.h:859:14: required from 'std::shared_ptr<_Tp> std::allocate_shared(const _Alloc&, _Args&& ...) [with _Tp = double; _Alloc = std::pmr::monotonic_buffer_resource; _Args = {}]' <source>:7:66: required from here /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/alloc_traits.h:78:11: error: no type named 'type' in 'struct std::__allocator_traits_base::__rebind<std::pmr::monotonic_buffer_resource, std::_Sp_counted_ptr_inplace<double, std::pmr::monotonic_buffer_resource, __gnu_cxx::_S_atomic>, void>' 78 | using __alloc_rebind | ^~~~~~~~~~~~~~ In file included from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr.h:52, from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/memory:84, from <source>:1: /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr_base.h: In instantiation of 'std::__shared_count<_Lp>::__shared_count(_Tp*&, std::_Sp_alloc_shared_tag<_Alloc>, _Args&& ...) [with _Tp = double; _Alloc = std::pmr::monotonic_buffer_resource; _Args = {}; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]': /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr_base.h:1371:71: required from 'std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::_Sp_alloc_shared_tag<_Tp>, _Args&& ...) [with _Alloc = std::pmr::monotonic_buffer_resource; _Args = {}; _Tp = double; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]' /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr.h:408:59: required from 'std::shared_ptr<_Tp>::shared_ptr(std::_Sp_alloc_shared_tag<_Tp>, _Args&& ...) [with _Alloc = std::pmr::monotonic_buffer_resource; _Args = {}; _Tp = double]' /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr.h:859:14: required from 'std::shared_ptr<_Tp> std::allocate_shared(const _Alloc&, _Args&& ...) [with _Tp = double; _Alloc = std::pmr::monotonic_buffer_resource; _Args = {}]' <source>:7:66: required from here /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr_base.h:682:16: error: use of deleted function 'std::pmr::monotonic_buffer_resource::monotonic_buffer_resource(const std::pmr::monotonic_buffer_resource&)' 682 | auto __pi = ::new (__mem) | ^~~~~~~~~~~~~ 683 | _Sp_cp_type(__a._M_a, std::forward<_Args>(__args)...); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In file included from <source>:2: /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/memory_resource:604:5: note: declared here 604 | monotonic_buffer_resource(const monotonic_buffer_resource&) = delete; | ^~~~~~~~~~~~~~~~~~~~~~~~~ In file included from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr.h:52, from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/memory:84, from <source>:1: /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr_base.h:546:33: note: initializing argument 1 of 'std::_Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp>::_Sp_counted_ptr_inplace(_Alloc, _Args&& ...) [with _Args = {}; _Tp = double; _Alloc = std::pmr::monotonic_buffer_resource; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]' 546 | _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args) | ~~~~~~~^~~
That long error message basically boils down to these 2 errors:
error: no type named 'type' in 'struct std::__allocator_traits_base::__rebind<std::pmr::monotonic_buffer_resource, std::_Sp_counted_ptr_inplace<double, std::pmr::monotonic_buffer_resource, __gnu_cxx::_S_atomic>, void>'
error: use of deleted function 'std::pmr::monotonic_buffer_resource::monotonic_buffer_resource(const std::pmr::monotonic_buffer_resource&)'
std::pmr::monotonic_buffer_resource
does not satisfy the requirements that std::allocate_shared()
expects, specifically:
All memory allocation is done using a copy of
alloc
, which must satisfy the Allocator requirements.
In particular, "a COPY of alloc
", which fails since monotonic_buffer_resource
's copy constructor is delete
'd so it can't be copied.
As @MilesBudnek stated in comments, you can wrap the monotonic_buffer_resource
inside a std::pmr::polymorphic_allocator
, which is designed to be used as an Allocator
for standard containers:
The class template
std::pmr::polymorphic_allocator
is an Allocator which exhibits different allocation behavior depending upon thestd::pmr::memory_resource
from which it is constructed.
For example:
#include <memory>
#include <memory_resource>
int main() {
char buffer[100];
std::pmr::monotonic_buffer_resource mbr(buffer, 100);
auto sp = std::allocate_shared<double, std::pmr::polymorphic_allocator<double>>(&mbr);
}
Alternatively:
#include <memory>
#include <memory_resource>
int main() {
char buffer[100];
std::pmr::monotonic_buffer_resource mbr(buffer, 100);
std::pmr::polymorphic_allocator<double> alloc(&mbr);
auto sp = std::allocate_shared<double>(alloc);
}