読者です 読者をやめる 読者になる 読者になる

C++1y 多相アロケータの提案

C++

N3525 Polymorphic Allocators


C++11現在の標準アロケータであるstd::allocatorは、コンパイル時にアロケータが管理する型を決定するから使いにくい。なのでアロケータにType Erasureを使ってインタフェースを改善しよう、というのがこの提案。


具体的には、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が抽象クラスという点については、改善の余地があると思いますが、おもしろい設計だとおもいます。