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, unlikeentity.Alternatively, replace the lambda with a struct (KamilCuk's answer).