Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create the simplest allocator with two template arguments

I'm extremely new to C++ memory management, but want to make my hands dirty building a simple allocator that would preallocate in advance enough memory for some container.

I've looked at Alexandrescu Loki library and tried to read some blogs, but all this was just to diffucult for me to grasp. I want to start from some primitive and working starting point, expand it and see how it evolves. This is what I have now and what I do understand (my starting point):

template <class T>
struct Allocator {

    Allocator(){};

    template <class U>
    Allocator(Allocator<U> const&);

    T* allocate(size_t s) {
        return static_cast<T*>(::operator new(s * sizeof(T)));
    }

    void deallocate(T* p, size_t s) {
        ::operator delete(p);
    }

    void construct(T* p, T const& val) {
        ::new((void *)p) T(val);
    }

    void destroy(T* p) {
        return ((T *) p)->~T();
    }

    using value_type = T;

};

So, I can now use it like so:

std::vector<int, Allocator<int> > vec;

This allocator is very simple and I understand what it does. I now want to expand it a little bit, so that my client code would look like:

std::vector<int, Allocator<int, 8> > vec;

I would now expect my code to allocate enough memory for 8 elements. I tried to expand my starting code with these lines:

template <class T, size_t T_num_els>
struct Allocator {

    template <class U, size_t U_num_els>
    Allocator(Allocator<U, U_num_els> const&);

    ... I keep all the rest without changes just for testing reason

but when I compile it, I get a crazy list of error messages, some messages tell about required substitution, rebind_alloc and no type named "type". So, how can I fix it. What correction should I make to my stepping stone code to allow my allocator have two template parameters?

like image 841
Jacobian Avatar asked Jan 02 '18 13:01

Jacobian


Video Answer


1 Answers

I think the problem is that you have a non-type template parameter. The allocator_traits adaptor does not seem to support that.

Some containers, like std::list<int>, will not allocate ints but some internal_node<int>. So it has to be able to transform an Allocator<int> into an Allocator<internal_node<int>>.

To create an allocator for such a type T, allocator_traits expects to either be able to do Alloc::rebind<T>::other from the original (C++98) allocator interface, or to use Alloc<T, Args...> when your allocator is Alloc<U, Args...>.

Neither of these two options match what can be done with your Allocator. The last one fails because the value 8 isn't a type that can match Args.

Possibly you can fix this by adding

template<class U>
struct rebind
{
   using other = Allocator<U, T_num_els>;
};
like image 198
Bo Persson Avatar answered Oct 02 '22 12:10

Bo Persson