Home > Back-end >  How to store a state of custom allocator used for allocation of different types
How to store a state of custom allocator used for allocation of different types

Time:05-11

In a situation where one needs to work with custom stateful allocator, what is the idiomatic way to store the state, if the state should be used to allocate objects of different types? E.g. if one needs a allocator-aware object, that uses data-structures of different types, such as the following:

struct Foo
{
    std::vector<int> ints;
    std::vector<double> doubles;
    void bar() { std::vector<std::string> strs; }
}

I tried two solutions:
(1)

template<typename Alloc>
struct Foo
{
    Foo(const Alloc& alloc) : alloc(alloc), ints(alloc), doubles(alloc) {}

    Alloc alloc;
    std::vector<int, typename std::allocator_traits<Alloc>::template rebind_alloc<int>> ints;
    std::vector<double, typename std::allocator_traits<Alloc>::template rebind_alloc<double>> doubles;
    void bar() { std::vector<std::string, typename std::allocator_traits<Alloc>::template rebind_alloc<std::string>> strs(alloc); }
};

custom_allocator<char> alloc(state); // any type, will be rebound
Foo<custom_allocator<char>> foo(alloc);

Assuming the state of the allocator is easy to copy, than this solution is fine, but writing the rebind machinery (typename allocator_traits::template rebind) and the fact that I have to specify (some) type (char) is giving me a headache.

(2)

template<template<typename> typename Alloc>
struct Foo
{
    struct dummy_t{};

    Foo(const Alloc<dummy_t>& alloc) : alloc(alloc), ints(alloc), doubles(alloc) {}

    Alloc<dummy_t> alloc;
    std::vector<int, Alloc<int>> ints;
    std::vector<double, Alloc<double>> doubles;
    void bar() { std::vector<std::string, Alloc<std::string>> strs(alloc); }
};

custom_allocator<char> alloc(state); // any type, will be rebound, or
custom_allocator alloc2(state); // if I make <T = char> in my allocator implementation
Foo<custom_allocator> foo(alloc);

Which seems better with the declaration noise, but is somehow different to how STL looks (as that accepts a specific allocator, whereas (2) accepts an allocator template).

Ideally I would want a single allocator (i.e. non-template) with templated construct, as that wouldn't require any rebinding/conversions, but that's sadly not what the STL containers accept.

Am I missing something obvious, or are these ((1) or (2)) the reasonable ways?

EDIT: In my proposals the state of the allocator is actually not shared between the vectors, but rather copied, but I am fine with that, as in my problem, the state is immutable.

CodePudding user response:

Maybe you can use pmr.

#include <vector>
#include <memory_resource>

struct foo {
    std::pmr::memory_resource& mem {*std::pmr::get_default_resource()};
    std::pmr::vector<int> vi{&mem};
    std::pmr::vector<double> vd{&mem};
};
  • Related