Thoughts from a C++ library developer.

Memory 0.4: Polishing, Error handling, Storage, Traits, Documentation and more

It took a really long time - three months minus one day - but I have finally finished version 0.4 of foonathan/memory. The release contains a lot of changes and has more than doubled the number of commits.


The interface is completely cleaned and I’ve got rid of the historically grown stuff. This required renaming or moving a lot of stuff, in particular:

  • raw_allocator_allocator is now std_allocator and moved to the new header std_allocator.hpp
  • raw_allocator_deallocator and raw_allocator_deleter are now simply allocator_deleter and allocator_deallocator in new hader deleter.hpp
  • raw_allocate_shared and raw_allocate_delete are likewise renamed into allocate_shared and allocate_delete since they can also handle normal Allocators
  • the jungle of allocator_type, impl_allocator or raw_allocator typedefs are all allocator_type, likewise for the getter, they’re all get_allocator() now
  • pool_allocator.hpp and stack_allocator.hpp are now named after their classes: memory_pool.hpp and memory_stack.hpp respectively; the other pool headers have gotten the memory_-prefix as well
  • allocator_adapter.hpp is now allocator_storage.hpp for a similar reason as the other headers

I’ve also added some missing features I’ve noticed while writing the documentation. They are many tiny things like the ability to specify a Mutex at almost every class or alias or more default template arguments for other classes.

Error handling

Another thing polished are the error handling facilites. Before they were a mess of various exceptions and calls to assert(). Now they use a well-defined interface and exception types.

But those facilites are customizable using handler functions. This allows a user-defined error handling even if exception support is disabled.

Allocator storage and traits improvement

The old allocator adapters are completely changed in the implementation. A new allocator_storage class template takes a StoragePolicy and stores a RawAllocator using it. The adapters like allocator_adapter or allocator_reference are now simply aliases for the allocator_storage template with a given policy.

Type-erased storage has been added as well, the tag type any_allocator can be specified as RawAllocator everywhere it is stored by an allocator_reference, like in std_allocator, allocator_deleter or allocator_reference itself. It activates a specialization of allocator_reference that uses type-erasure to store a generic reference to any RawAllocator.

The default template specialization of allocator_traits has been overhauled, too. It is now able to handle a broader range of types including all Allocator classes! The minimum required interface for it has been reduced to allocate_node and deallocate_node only, the defaults in case of missing member functions are improved and there are better error messages if a type does not fulfill the criteria. The addition of supporting the Allocator concept allows passing an Allocator anywhere a RawAllocator is required.

Nodesize Debugger

The problem with pool allocators are that they require a node size. For example, if you want to use a std::list with a memory::memory_pool you write:

memory::memory_pool<> pool(???, 4096);
memory::list<int, decltype(pool)> list(pool);

At the point of ??? belongs the size of each node in the pool. But what should it be? 16? 32? It depends on the size of each node in the std::list of int. But the internal node size is not accessible, so there is no easy and portable way to get its size.

So I’ve added the nodesize_dbg. This tool debugs the node sizes of STL containers by passing them a custom allocator that tracks the size of the type it is rebound too. It automatically generates constants in the header container.hpp that contains the appropriate node sizes, allowing us to write:

memory::memory_pool<> pool(memory::list_node_size<int>::value, 4096);
memory::list<int, decltype(pool)> list(pool);

Other things worth mentioning

  • new documentation and tutorial hosted here, at
  • all functionality except those that is an explicit wrapper around the standard library - like smart_ptr.hpp and container.hpp - can work on a freestanding implementation
  • the compatibility checks are outsourced to foonathan/compatibility
  • bugfixes, bugfixes and bugfixes, most notably regarding alignment issues with activated fence memory

This post was made possible by my Patreon supporters. If you'd like to support me as well, please head over to my Patreon and do so! One dollar per month can make all the difference.