#include <iostream>
#include <vector>
#include <list>
#include <limits>
using namespace std;
struct memory_manager
{
memory_manager() : allocations(0) {}
void* allocate(size_t s)
{
++allocations;
return new char[s];
}
void deallocate(void* mem)
{
delete[] reinterpret_cast<char*>(mem);
--allocations;
}
size_t allocations;
}
the_manager;
template <typename T>
class custom_allocator
{
public:
typedef T value_type;
typedef value_type* pointer;
typedef value_type const* const_pointer;
typedef value_type& reference;
typedef value_type const& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
pointer allocate(size_type size, const void* = nullptr)
{
void* mem = the_manager.allocate(size * sizeof(value_type));
return reinterpret_cast<pointer>(mem);
}
void deallocate(pointer mem, size_type)
{
the_manager.deallocate(mem);
}
size_type max_size() const
{
return numeric_limits<size_t>::max() / sizeof(value_type);
}
////////////////////////////////////////////////////////////////////////////
// boilerplate follows
custom_allocator() {}
custom_allocator(const custom_allocator&) {}
template <typename Other>
custom_allocator(const custom_allocator<Other>&) {}
custom_allocator& operator=(const custom_allocator&) { return *this; }
template <class other>
custom_allocator& operator=(const custom_allocator<other>&) { return *this; }
template <typename Other>
struct rebind { typedef custom_allocator<Other> other; };
pointer address(reference ref) const
{
return &ref;
}
const_pointer address(const_reference ref) const
{
return &ref;
}
void construct(pointer ptr, const value_type& val)
{
::new(ptr)value_type(val);
}
void destroy(pointer ptr)
{
ptr->~value_type();
}
};
template <typename T>
using custom_vector = std::vector<T, custom_allocator<T>>;
template <typename T>
using custom_list = std::list<T, custom_allocator<T>>;
struct custom_tag {};
custom_tag the_tag;
void* operator new(size_t size, const custom_tag&)
{
return the_manager.allocate(size);
}
void operator delete(void* mem, const custom_tag&)
{
the_manager.deallocate(mem);
}
#define custom_new new(the_tag)
#define custom_delete(mem) ::operator delete(mem, the_tag);
#define custom_delete_ar(mem) ::operator delete[](mem, the_tag);
int main()
{
auto x = custom_new custom_list<int>;
custom_delete(x);
cout << the_manager.allocations << endl;
return 0;
}