Save memory resource context so that every nested container uses same resource with initializer_list

52 Views Asked by At

I'm using a polymorphic memory source to initialize the elements of a deeply nested struct. You might know that this is not so trivial, as the allocator has to be propogated through every object. With initializer lists however this is afaik impossible even, because you can't pass allocator information along with initializer lists at compile time. So I thought maybe there's a way to contextually "save" the allocator context so that all subobjects are also aware of it and can use the same allocator during initialization with an initializer list. Something along the lines of this:

Demo

#include <array>
#include <memory_resource>
#include <variant>
#include <cstdio>


template <typename Alloc>
struct allocator_guard
{
    Alloc allocator_;

    allocator_guard(std::pmr::memory_resource* res) {
        // bring up allocator context
    }

    ~allocator_guard() {
        // shut down allocator context
    }
};


struct complicated_nested_struct;

using val = std::variant<std::monostate, int, bool, std::initializer_list<complicated_nested_struct>>;

struct complicated_nested_struct : val
{
    using val::variant;

    auto get_allocator() {
        struct {
            void allocate() {
                printf("Would allocate, but where? How to get context from allocator_guard?\n");
            }
        } a;
        return a;
    }

    complicated_nested_struct(std::initializer_list<complicated_nested_struct>) {
        get_allocator().allocate(); // allocates for something, who knows what?
    }
};


int main()
{
    std::array<std::byte, 2048> buf;

    std::pmr::monotonic_buffer_resource res{ buf.data(), buf.size() };

    {
        allocator_guard<std::pmr::polymorphic_allocator<std::byte>>{ &res };

        complicated_nested_struct a = {56, {1, false, { 20, true }} }; // <-- all subobjects should now use res!
    }
}

Now I don't know how to create the link between the allocator guard and the allocating container. I could template on a callback lambda, but that would bloat my code for every instance of the container. Are there other ways?

0

There are 0 best solutions below