4

I would like to implemented a custom allocator for node-based containers like std::unordered_map or std::list. For that allocator I need to specify the size of the nodes. How do I get this? I know in C++17 at least std::unordered_map has a node_type, but I'm currently bound to C++11

martinus
  • 17,736
  • 15
  • 72
  • 92
  • Isn't the allocator only responsible for the memory allocation of the objects you store in the map and not for the nodes? So why do you need the size of the node? – t.niese Sep 12 '19 at 16:27
  • 2
    No, the allocator is used to allocate the nodes which are the value_type plus some extra info. It also allocates some large arrays. On my machine for `using Map = std::unordered_map` I get `sizeof(Map::value_type) == 16`, but the allocator is actually called to allocate 24 bytes for one entry – martinus Sep 12 '19 at 16:50
  • Ok, never realized that it changes the template of the allocator to be a node of the given type. But within your custom allocator class, you know the type (and therefore size) of the node due to the template argument, so what is the problem with using this information? Do you need that information before the allocator is constructed? (If you write `std::list>` the allocator instance created is `Allocator>`). – t.niese Sep 12 '19 at 17:49
  • @t.niese The standard containers are actually required to call `typename std::allocator_traits::rebind_alloc` to allocate internal objects (nodes) of type `Node`. – L. F. Sep 13 '19 at 01:36
  • @martinus Do you want to get the size of the internal node programmatically? Or do you want to tell the implementation to use nodes of a specific size? – L. F. Sep 13 '19 at 01:37
  • did you find an answer to that? There's an old question that effectivelly says it's not possible: https://stackoverflow.com/questions/22951378/how-do-you-determine-the-size-of-the-nodes-created-by-a-stdmap-for-use-with Given that, I don't really see any use for allocator customization – Sergey Kolesnik Mar 07 '23 at 23:20
  • @SergeyKolesnik no, I tried hard but this is not possible. Also each implementation (MSVC, libc++, libstdc++) does it differently, at least for `std::unordered_map`, so it is impractical to hardcode something. – martinus Mar 20 '23 at 07:56
  • I had some thought about the case, when you need a pool allocator for an auxiliary container and you know how many elements will be allocated in advance. One can try to implement a statefull allocator that stores number of elements thta will be allocated. Upon the first allocation it would allocated the whole pool using the type size requested by the caller (container). But it is a wild guess and I don't see if it is worth the try. Better to give up on the Standard Library completelly. – Sergey Kolesnik Mar 20 '23 at 09:15
  • @SergeyKolesnik unfortunately that doesn't work generically, e.g. in MSVC they allocate some control structure first for the map, so just using the size of the first allocation doesn't work. I have implemented my pool allocator now a bit differenltly so it supports multiple allocation sizes, up to a given template size. I just have to choose the size large enough, typically `sizeof(value_type) + sizeof(void*)*4` works. – martinus Apr 13 '23 at 12:52

0 Answers0