For example:

struct Foo {
    MyPoolAlloc<char> pool;
    std::vector<int , MyPoolAlloc<char>> vec_int; // The wrapper allocator would replace MyPoolAlloc<> here.
    std::vector<std::function<void()> , MyPoolAlloc<char>> vec_funcs; // The wrapper allocator would replace MyPoolAlloc<> here.

    Foo() : vec_int(pool) , vec_funcs(pool) {}

    // I want to store lambdas with captured variables using the custom allocator as well:
    template<typename Func>
    void emplace_back(const Func& func) {
        vec_funcs.emplace_back(std::allocator_arg , pool , func);
    }
};

In the above code, I want ALL allocations (besides the pool itself) to pull from the same pool object. Is the best way to do this writing a wrapper allocator that stores a reference to an actual stateful allocator object? And then pass the following into the constructors (example):

: vec_int ((MyWrapperAlloc<char>(pool)));

Is there a cleaner way to do this than writing a whole extra wrapper class for MyPoolAlloc<>?

1

There are 1 answers

0
Potatoswatter On BEST ANSWER

The standard "Allocator" concept would have been better named "AllocatorReference." Each object either refers to a global instance (stateless) or to an external object (stateful).

Either way, the allocator instance within an allocator-aware container does not own a memory pool by itself. It's only a proxy. Note that allocator objects are often copied as they are rebound and returned by value. You don't want vector::get_allocator to copy a whole memory pool.

So, yes, you need two classes.

  1. The "wrapper," "proxy," or "reference" which satisfies the standard Allocator requirements and takes a template parameter for the allocated type.

  2. The memory pool which has nothing to do with the Allocator interface but does know how to perform allocations.