Search code examples
c++stlpolymorphismallocator

what is the usage of the template parameter of the std::pmr::polymorphic_allocator?


I'm currently learning the polymorphic allocator, I watched some videos and trying to understand it. If I have this code:

class MyClass {
public:
    MyClass(int val = 0) : m_val(val) {
        std::cout << "MyClass constructed with value: " << val << std::endl;
    }
    ~MyClass() {
        std::cout << "MyClass destroyed with value: " << m_val << std::endl;
    }
private:
    int m_val;
};
int main() {
    char buffer[1024];
    std::size_t buffer_size = sizeof(buffer);
    // Use a monotonic buffer resource
    {
        std::pmr::monotonic_buffer_resource buffer_resource{buffer, buffer_size, std::pmr::null_memory_resource()};
        std::pmr::polymorphic_allocator<byte> allocator{ &buffer_resource };
        //std::pmr::polymorphic_allocator<MyClass> allocator{ &buffer_resource }; //still OK to use
        {
            std::pmr::vector<MyClass> vec(allocator);
            vec.reserve(256);
            for(int i = 0; i < 256; i++){
                vec.emplace_back(i);
            }
        }
    }
    return 0;
}

What is the difference between std::pmr::polymorphic_allocator<byte> and std::pmr::polymorphic_allocator<MyClass>? Why both can work fine?


Solution

  • From std::vector:

    Allocator - An allocator that is used to acquire/release memory and to construct/destroy the elements in that memory. The type must meet the requirements of Allocator. The behavior is undefined (until C++20) / The program is ill-formed (since C++20) if Allocator::value_type is not the same as T.

    So, if Allocator::value_type is not the same as MyClass:

    • The behavior is undefined (until C++20)
    • The program is ill-formed (since C++20)

    The correct way to use it is therefore to use std::pmr::polymorphic_allocator<MyClass>.

    Why both can work fine?

    The std::pmr::vector<MyClass> constructor ...

    constexpr explicit vector(
        const std::pmr::polymorphic_allocator<MyClass>& alloc) noexcept;
    

    ... converts the allocator you supply into a std::pmr::polymorphic_allocator<MyClass> which uses the same memory resource as your allocator.