I propose a new allocator that uses global (i.e. static duration) memory.
Here's my current experimental code:
#include <cstddef> /* size_t */
#include <new> /* Only for bad_alloc */
static int this_translation_unit; /* This serves the same purpose as
__FILE__ */
template<typename T, std::size_t t_capacity, std::size_t t_counter,
int *t_file = &this_translation_unit>
class StaticAllocator {
protected:
static T buf[t_capacity];
public:
typedef T value_type;
template<typename U>
struct rebind {
typedef StaticAllocator<U, t_capacity, t_counter, t_file> other;
};
T *allocate(std::size_t const n)
{
if (n > t_capacity)
throw std::bad_alloc();
return buf;
}
void deallocate(T *, std::size_t)
{
/* Do Nothing */
}
};
template<typename T, std::size_t t_capacity, std::size_t t_counter, int *t_file>
T StaticAllocator<T, t_capacity, t_counter, t_file>::buf[t_capacity];
using std::size_t;
#include <vector>
using std::vector;
#include <iostream>
using std::cout;
using std::endl;
auto main(void) -> int
{
vector< char, StaticAllocator< char, 4, __COUNTER__ > > v;
v.push_back('a');
v.push_back('b');
v.push_back('c');
v.push_back('d');
for (auto const &elem : v)
cout << elem << endl;
vector< char, StaticAllocator< char, 4, __COUNTER__ > > v2;
v2.push_back('x');
v2.push_back('y');
v2.push_back('z');
for (auto const &elem : v2)
cout << elem << endl;
// Now try the first vector again
for (auto const &elem : v)
cout << elem << endl;
}
The trick I am using with "this_translation_unit" works fine on GNU
and Clang, however it fails to compile on Microsoft because the
variable has internal linkage. I'm sure we can do this another way
using something from the Boost preprocessor library. The preprocessor
macro __COUNTER__ is available on every compiler I know of.
Frederick
P.S. This is my second idea posted to the Boost dev list. My first one
was "istream_iterator_limited".