Я только что завершил личный проект по переопределению операторов new и delete и в процессе узнал о классах распределителей. Прочитав несколько онлайн-справочников, в том числе cppreference.com, я заметил, что многие функции описываются как необязательные.
Мой вопрос заключается в том, как получатель распределителя, например. std::set
, работать, если его полученный аллокатор только опционально реализует функции и типы?
Я бы понял, если бы распределитель должен был быть производным от некоторого базового класса, имеющего реализации по умолчанию для всех функций, но, похоже, для распределителей не требуется наследования.
Или это рассуждение о том, что о необходимости реализации этих необязательных функций можно было бы узнать из-за ошибки компиляции?
В качестве справки, вот моя первая попытка распределителя, который я использовал в качестве третьего аргумента шаблона для std::set
. Я работал на существующем примере, и поэтому я считаю, что многое из того, что я реализовал, может быть ненужным, но я пока не понимаю, как судить, будет ли необходимо, если я решу использовать распределитель с каким-либо другим контейнером STL в будущем. Если, опять же, ожидание не состоит в том, чтобы понять это на основе ошибок компиляции...?
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; }
};