Search code examples
c++allocator

trivial allocator aware container?


I am studying/playing with allocators trying to understand how it works. But I run into problems trying to implement trivial container that accepts an allocator. For now I ended up with this:

template<class T, class Allocator =std::allocator<T>> class Container {
public:
    using allocator_type    = Allocator;
    using value_type        = T;
    using pointer           = typename std::allocator_traits<allocator_type>::pointer;
    using reference         = value_type&;
    using size_type         = std::size_t;

    Container( size_type n =0 , const allocator_type& allocator =allocator_type() ){
        std::cout << "ctor" << std::endl;
        allocator.allocate(n);
    };
};

int main(int argc, const char* argv[]){
    Container<int> c {5};
    return 0;
}

It gives me an error member function 'allocate' not viable: 'this' argument has type 'const allocator_type' (aka 'const std::__1::allocator<int>'), but function is not marked const

How to fix that error, please? Am I missing something ? I intend to use traits later but would like to make it work using the old way first.


Solution

  • Your line

    allocator.allocate(n);
    

    attempts to call the allocate method of allocator, which is not defined as a const method. If you look, though, the type of allocator is const allocator_type&, that is, a const reference to allocator_type.

    How can you use it then? One thing you can usually do with a const object (or reference to one) is to construct a different non-const object from it. This, for example, builds:

    allocator_type(allocator).allocate(n);
    

    As SergeyA correctly notes in the comments, it is fairly common not to construct a temporary ad-hoc allocator_type, but rather make such a member:

        allocator_type m_alloc; // Should probably be private
    
        Container( size_type n =0 , const allocator_type& allocator =allocator_type() ) : 
                m_alloc{allocator}{
            std::cout << "ctor" << std::endl;
            m_alloc.allocate(n);
        };