Re: do allocators have to be stateless?
Doug Harrison [MVP] wrote:
Sorry, I can't explain that. Can you verify it isn't being called?
OK, I did some checking and it is very strange indeed... :)
I attach the allocator code at the bottom. Just instantiating
std::set<int, std::less<int>, MyAlloc<int> > in main produces following
output:
default
copy
copy
copy
copy
and then an exception thrown from MYAlloc::allocate. debugger shows
values for max_size_ and cur_size_ as 0xcccccccc...
Code:
struct limit_reached: public std::runtime_error
{
limit_reached(): std::runtime_error("set allocation limit reached"){}
};
template <class T>
class MyAlloc {
friend class SetBitMap;
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
template <class U>
struct rebind {
typedef MyAlloc<U> other;
};
pointer address (reference value) const {
return &value;
}
const_pointer address (const_reference value) const {
return &value;
}
MyAlloc() throw(): max_size_(1024), cur_size_(0) {
std::cerr << "default" << std::endl;
}
MyAlloc(const MyAlloc & a) throw():
max_size_(a.max_size_), cur_size_(a.cur_size_) {
std::cerr << "copy" << std::endl;
}
MyAlloc & operator=(const MyAlloc & a)
{
if (&a != this)
{
max_size_ = a.max_size_;
cur_size_ = a.cur_size_;
std::cerr << "assign" << std::endl;
}
else
std::cerr << "assign self" << std::endl;
return *this;
}
template <class U>
MyAlloc (const MyAlloc<U>&) throw() {
}
~MyAlloc() throw() {
}
size_type max_size () const throw() {
return max_size_;
}
pointer allocate (size_type num, const void* = 0) {
if (cur_size_ + num > max_size_)
throw limit_reached();
pointer ptr = (pointer) malloc(num*sizeof(T));
if (ptr == 0)
throw std::bad_alloc();
cur_size_ += num;
return ptr;
}
void construct (pointer p, const T& value) {
new((void*)p)T(value);
}
void destroy (pointer p) {
p->~T();
}
void deallocate (pointer p, size_type num) {
free (p);
cur_size_ -=num;
}
private:
int max_size_;
int cur_size_;
};
template <class T1, class T2>
bool operator== (const MyAlloc<T1>&,
const MyAlloc<T2>&) throw() {
return true;
}
template <class T1, class T2>
bool operator!= (const MyAlloc<T1>&,
const MyAlloc<T2>&) throw() {
return false;
}