I have a class entity
that uses a stateful polymorphic allocator and std::unique_ptr
to manage a resource. Naturally, I have to provide a custom deleter for the unique_ptr that pairs with allocator_.new_object()
that I pass in the constructor. However, as this deleter must use the same allocator again, I need to access the allocator member from within the deleter. This appears to be quite tricky. Using this answer I was able to get this far, but now gcc complains that struct entity
is incomplete. Any way to get around this?
#include <string_view>
#include <cstdio>
#include <memory>
#include <memory_resource>
#include <type_traits>
struct StaticTimer_t
{
std::string_view hello_ = "Hello World!";
};
template <typename T> requires (std::is_pointer_v<T>)
auto deleter(T e) {
return [e](StaticTimer_t* p){ e->get_allocator().delete_object(p); };
}
struct entity
{
using allocator_t = std::pmr::polymorphic_allocator<std::byte>;
auto get_allocator() -> allocator_t
{
return allocator_;
}
entity(allocator_t allocator = {})
: allocator_( allocator )
, ptr_( allocator_.new_object<StaticTimer_t>(), deleter(this) )
{ }
auto print()
{
printf("%s\n", ptr_.get()->hello_.data());
}
allocator_t allocator_;
std::unique_ptr<StaticTimer_t, decltype(deleter<entity*>(nullptr))> ptr_;
};
int main()
{
entity e;
e.print();
}
Error:
<source>:14:38: error: invalid use of incomplete type 'struct entity'
14 | return [e](StaticTimer_t* p){ e->get_allocator().delete_object(p); };
| ~~~^~~~~~~~~~~~~
<source>:17:8: note: forward declaration of 'struct entity'
17 | struct entity
| ^~~~~~
Note: I'm looking for a way to get around std::function!
Pass the allocator directly instead of the entity
. It is all you need and it is complete where you need it to be, unlike entity
.
using allocator_t = std::pmr::polymorphic_allocator<std::byte>;
auto deleter(allocator_t e) {
return [e](StaticTimer_t* p) mutable { e.delete_object(p); };
}
entity(allocator_t allocator = {})
: allocator_( allocator )
, ptr_( allocator_.new_object<StaticTimer_t>(), deleter(allocator_) )
{ }
std::unique_ptr<StaticTimer_t, decltype(deleter(std::declval<allocator_t>()))> ptr_;
Alternatively, replace the lambda with a struct (KamilCuk's answer).