C++11現在の標準アロケータであるstd::allocator
具体的には、polymorphic_allocatorとmemory_resourceという、大きく2つのクラスを用意する。使い方:
// 固定サイズアロケータ。 // 抽象クラスであるmemory_resourceを継承して実装する class FixedBufferResource : public memory_resource { void *m_next_alloc; std::size_t m_remaining; public: FixedBufferResource(void *buffer, std::size_t size) : m_next_alloc(buffer), m_remaining(size) { } virtual void *allocate(std::size_t sz, std::size_t alignment) { if (std::align(alignment, sz, m_next_alloc, m_remaining)) return m_next_alloc; else throw std::bad_alloc(); } virtual void deallocate(void *, std::size_t, std::size_t) { } virtual bool is_equal(std::polyalloc::memory_resource& other) const noexcept { return this == &other; } }; char buffer[1024]; FixedBufferResource buf_rsrc(&buffer, 1024); // stringとvectorで同じアロケータオブジェクトを使う basic_string<char, polymorphic_allocator<char>> s(&buf_rsrc); vector<int, polymorphic_allocator<int>> v(&buf_rsrc);
memory_resourceは、非テンプレートな抽象クラス。polymorphic_allocatorはクラステンプレートで、memory_resourceの単純なラッパー。
アロケータを使う各クラスは、その型に規定されたアロケータオブジェクトを持ち、そのクラスの外からは、型を規定しないアロケータを渡す、というshared_ptrのカスタムデリータとかとは逆のアプローチでのType Erasureですね。
memory_resourceが抽象クラスという点については、改善の余地があると思いますが、おもしろい設計だとおもいます。