I just completed a personal project on overriding operator new and delete, and came to learn about allocator classes in the process. Having read several online references, including cppreference.com, I note that many functions are described as optional.
My question is how does an allocator recipient, e.g. std::set
, work if its received allocator only optionally implements functions and types?
I would understand if the allocator was required to derive from some base class that had default implementations for all functions, but there seems no inheritance requirement for allocators.
Or is the reasoning that one would be alerted to the need to implement these optional functions by a compilation error?
As reference, here is my first attempt at an allocator which I used as the third template argument to a std::set
. I worked off an existing example, and so I believe that much of what I have implemented may be unnecessary, but I don't yet understand how to judge would be necessary if I choose to use an allocator with some other STL container in future. Unless, again, the expectation is to figure it out based on compile errors...?
template <typename T>
class Allocator // Custom allocator for use by AllocSet::mAllocatedPtrs to avoid infinite recursion
{ // (because inserting an element in std::set calls ::operator new, which is overridden to add to AllocSet::mAllocatedPtrs).
public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef const T* const_pointer;
typedef const T& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
template <typename U>
struct rebind { typedef Allocator<U> other; };
Allocator() { }
template <typename U> Allocator(const Allocator<U>&) { }
virtual ~Allocator() { }
pointer allocate(size_t numT) { return (T*)(malloc(numT * sizeof(T))); }
void deallocate(pointer p, size_type st) { free(p); }
size_type max_size() { return size_type(-1); }
reference operator=(const_reference) { return *this; }
template <typename U> reference operator=(const Allocator<U>&) { return *this; }
template <typename U> bool operator==(const Allocator<U>&) { return true; }
template <typename U> bool operator!=(const Allocator<U>&) { return false; }
pointer address(reference r) { return &r; }
const_pointer address(const_reference r) { return &r; }
};