Help with STL allocators

M

mar00ned

Hi,

I have a written a custom allocator for STL, on the lines of default
allocator as follows :

template <class T>
class pool_allocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;

template <class U>
struct rebind { typedef pool_allocator<U> other; };

pointer address(reference x) const {return &x;}
const_pointer address(const_reference x) const {return &x;}

pool_allocator(){}
pool_allocator(const pool_allocator&) {}
template <class U>
pool_allocator (const pool_allocator<U>&) {}
~pool_allocator(){}


size_type max_size() const throw() {return size_t(-1) /
sizeof(value_type);}

pointer allocate(size_type size, const void* hint = 0)
return static_cast<pointer>(mem_.allocate(size*sizeof(T)));
}

void construct(pointer p, const T& val)
{
new(static_cast<void*>(p)) T(val);
}
void construct(pointer p)
{
new(static_cast<void*>(p)) T();
}

void destroy(pointer p){p->~T();}
void destroy(char* ){}
void destroy(void* ){}


void deallocate(pointer p, size_type n)
{
mem_.deallocate(p, n);
}
void deallocate(void *p, size_type n)
{
mem_.deallocate(p, n);
}
void deallocate(pointer p)
{
mem_.deallocate(p);
}
void deallocate(void *p)
{
mem_.deallocate(p);
}

static void dump(){
mem_.dump();
}

private:

static pool mem_;
};

//template <class T> pool pool_allocator<T>::mem_;

template <class T, class U>
inline bool operator==(const pool_allocator<T>&, const
pool_allocator<U>){return true;}

template <class T, class U>
inline bool operator!=(const pool_allocator<T>&, const
pool_allocator<U>){return false;}

I do a simple thing like : map<int, float, less<int>,
pool_allocator<pair<int, float> > > m;
I try to build it on HPUX using aCC (aCC: HP ANSI C++ B3910B A.03.39
). But unfortunately, I am facing following errors :

Error 874: "/opt/aCC/include/memory", line 529 # A non-void type is
required for specialization instead of 'void' since the template
creates a reference to that type.
typedef T& reference;
^^^^^^^^^
Error 874: "/opt/aCC/include/memory", line 530 # A non-void type is
required for specialization instead of 'void' since the template
creates a reference to that type.
typedef const T& const_reference;
^^^^^^^^^^^^^^^
Error 874: "/opt/aCC/include/memory", line 546 # A non-void type is
required for specialization instead of 'void' since the template
creates a reference to that type.
pointer address (T& x)
^^^^^^^
Error 874: "/opt/aCC/include/memory", line 546 # A non-void type is
required for specialization instead of 'void' since the template
creates a reference to that type.
pointer address (T& x)
^^^^^^^
Error 874: "/opt/aCC/include/memory", line 595 # A non-void type is
required for specialization instead of 'void' since the template
creates a reference to that type.
allocator_interface<Allocator,T>::construct(pointer p, const T&
val)
^^^^^^^^^
Error 874: "/opt/aCC/include/memory", line 595 # A non-void type is
required for specialization instead of 'void' since the template
creates a reference to that type.
allocator_interface<Allocator,T>::construct(pointer p, const T&
val)


I am not very good at this ... any reasons why this could be happening
?

~mar00ned
 
J

John Harrison

mar00ned said:
Hi,

I have a written a custom allocator for STL, on the lines of default
allocator as follows :

template <class T>
class pool_allocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;

template <class U>
struct rebind { typedef pool_allocator<U> other; };

pointer address(reference x) const {return &x;}
const_pointer address(const_reference x) const {return &x;}

pool_allocator(){}
pool_allocator(const pool_allocator&) {}
template <class U>
pool_allocator (const pool_allocator<U>&) {}
~pool_allocator(){}


size_type max_size() const throw() {return size_t(-1) /
sizeof(value_type);}

pointer allocate(size_type size, const void* hint = 0)
return static_cast<pointer>(mem_.allocate(size*sizeof(T)));
}

void construct(pointer p, const T& val)
{
new(static_cast<void*>(p)) T(val);
}
void construct(pointer p)
{
new(static_cast<void*>(p)) T();
}

void destroy(pointer p){p->~T();}
void destroy(char* ){}
void destroy(void* ){}


void deallocate(pointer p, size_type n)
{
mem_.deallocate(p, n);
}
void deallocate(void *p, size_type n)
{
mem_.deallocate(p, n);
}
void deallocate(pointer p)
{
mem_.deallocate(p);
}
void deallocate(void *p)
{
mem_.deallocate(p);
}

static void dump(){
mem_.dump();
}

private:

static pool mem_;
};

//template <class T> pool pool_allocator<T>::mem_;

template <class T, class U>
inline bool operator==(const pool_allocator<T>&, const
pool_allocator<U>){return true;}

template <class T, class U>
inline bool operator!=(const pool_allocator<T>&, const
pool_allocator<U>){return false;}

I do a simple thing like : map<int, float, less<int>,
pool_allocator<pair<int, float> > > m;
I try to build it on HPUX using aCC (aCC: HP ANSI C++ B3910B A.03.39
). But unfortunately, I am facing following errors :

Error 874: "/opt/aCC/include/memory", line 529 # A non-void type is
required for specialization instead of 'void' since the template
creates a reference to that type.
typedef T& reference;
^^^^^^^^^
Error 874: "/opt/aCC/include/memory", line 530 # A non-void type is
required for specialization instead of 'void' since the template
creates a reference to that type.
typedef const T& const_reference;
^^^^^^^^^^^^^^^
Error 874: "/opt/aCC/include/memory", line 546 # A non-void type is
required for specialization instead of 'void' since the template
creates a reference to that type.
pointer address (T& x)
^^^^^^^
Error 874: "/opt/aCC/include/memory", line 546 # A non-void type is
required for specialization instead of 'void' since the template
creates a reference to that type.
pointer address (T& x)
^^^^^^^
Error 874: "/opt/aCC/include/memory", line 595 # A non-void type is
required for specialization instead of 'void' since the template
creates a reference to that type.
allocator_interface<Allocator,T>::construct(pointer p, const T&
val)
^^^^^^^^^
Error 874: "/opt/aCC/include/memory", line 595 # A non-void type is
required for specialization instead of 'void' since the template
creates a reference to that type.
allocator_interface<Allocator,T>::construct(pointer p, const T&
val)


I am not very good at this ... any reasons why this could be happening
?

You need to create a specialised void allocator. Since you cannot allocate
void objects this allocator is very simple.

template <>
class pool_allocator<void>
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef void* pointer;
typedef const void* const_pointer;

template <class U>
struct rebind { typedef pool_allocator<U> other; };

};

Something like that anyway. The particular error you were getting were
because the compiler was trying to substitute void for T in your
unspecialised template and coming up with code like this

typedef void& reference;

which is illegal because you cannot have a void reference.

john
 
R

Rohit Mattoo

My allocator looks like this now :



template <class T> class pool_allocator;
template <>
class pool_allocator<void>
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef void* pointer;
typedef const void* const_pointer;
template <class U>
struct rebind { typedef pool_allocator<U> other; };

};

template <class T>
class pool_allocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
....

but unfortunately the error havent stopped.

Thanks and regards,
~mar00ned
 
J

John Harrison

Rohit Mattoo said:
My allocator looks like this now :



template <class T> class pool_allocator;
template <>
class pool_allocator<void>
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef void* pointer;
typedef const void* const_pointer;
template <class U>
struct rebind { typedef pool_allocator<U> other; };

};

template <class T>
class pool_allocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
....

but unfortunately the error havent stopped.

Thanks and regards,
~mar00ned

I think you should put your specialised template after your generic one, not
before.

john
 
R

Rohit Mattoo

Unfortunately this hasnt worked either :

#ifndef POOL_ALLOCATOR_H_INCLUDED_GF
#define POOL_ALLOCATOR_H_INCLUDED_GF

#include <map>
#include "pool.h"


template <typename T>
class pool_allocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;

template <typename U>
struct rebind { typedef pool_allocator<U> other; };

pointer address(reference x) const {return &x;}
const_pointer address(const_reference x) const {return &x;}

pool_allocator(){}
pool_allocator(const pool_allocator&) {}
template <typename U>
pool_allocator (const pool_allocator<U>&) {}
~pool_allocator(){}


size_type max_size() const throw() {return size_t(-1) /
sizeof(value_type);}

pointer allocate(size_type size, const void* hint = 0)
{
return static_cast<pointer>(mem_.allocate(size*sizeof(T)));
}

void construct(pointer p, const T& val)
{
new(static_cast<void*>(p)) T(val);
}
void construct(pointer p)
{
new(static_cast<void*>(p)) T();
}

void destroy(pointer p){p->~T();}
void destroy(char* ){}
void destroy(void* ){}


void deallocate(pointer p, size_type n)
{
mem_.deallocate(p, n);
}
void deallocate(void *p, size_type n)
{
mem_.deallocate(p, n);
}
void deallocate(pointer p)
{
mem_.deallocate(p);
}
void deallocate(void *p)
{
mem_.deallocate(p);
}

static void dump(){
mem_.dump();
}

private:

static pool mem_;
};

template <>
class pool_allocator<void>
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef void* pointer;
typedef const void* const_pointer;
template <typename U>
struct rebind { typedef pool_allocator<U> other; };
pool_allocator() {}
~pool_allocator() {}
};



template <typename T> pool pool_allocator<T>::mem_;

template <typename T, typename U>
inline bool operator==(const pool_allocator<T>&, const
pool_allocator<U>){return true;}

template <typename T, typename U>
inline bool operator!=(const pool_allocator<T>&, const
pool_allocator<U>){return false;}

template<typename Key, typename Value, class Traits = less<Key> >
struct PooledMap
{
typedef map<Key, Value, Traits,pool_allocator<pair<Key, Value> > > Type;
};
#endif
 
T

Tom Widmer

template<typename Key, typename Value, class Traits = less<Key> >
struct PooledMap
{
typedef map<Key, Value, Traits,pool_allocator<pair<Key, Value> > > Type;

That should be:
typedef map<Key, Value,
Traits, pool_allocator<pair<const Key, Value> > > Type;

What's the error you're getting now?

Tom
 
J

John Harrison

Rohit Mattoo said:
Unfortunately this hasnt worked either :

I took this code (I had to fake the pool object) and it compiled fine. The
only change I had to make from your code was to remove the void* and char*
versions of destroy (I don't know why you put them there).

Maybe you have a problem with your compiler, your error messages indicate
that it is ignoring the void specialised version of pool_allocator.


#include <map>

class pool
{
public:
void* allocate(std::size_t);
void deallocate(void*, std::size_t);
};

template <typename T>
class pool_allocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;

template <typename U>
struct rebind { typedef pool_allocator<U> other; };

pointer address(reference x) const {return &x;}
const_pointer address(const_reference x) const {return &x;}

pool_allocator(){}
pool_allocator(const pool_allocator&) {}
template <typename U>
pool_allocator (const pool_allocator<U>&) {}
~pool_allocator(){}


size_type max_size() const throw() {return size_t(-1) /
sizeof(value_type);}

pointer allocate(size_type size, const void* hint = 0)
{
return static_cast<pointer>(mem_.allocate(size*sizeof(T)));
}

void construct(pointer p, const T& val)
{
new(static_cast<void*>(p)) T(val);
}
void construct(pointer p)
{
new(static_cast<void*>(p)) T();
}

void destroy(pointer p){p->~T();}


void deallocate(pointer p, size_type n)
{
mem_.deallocate(p, n);
}
void deallocate(void *p, size_type n)
{
mem_.deallocate(p, n);
}
void deallocate(pointer p)
{
mem_.deallocate(p);
}
void deallocate(void *p)
{
mem_.deallocate(p);
}

static void dump(){
mem_.dump();
}

private:

static pool mem_;
};

template <>
class pool_allocator<void>
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef void* pointer;
typedef const void* const_pointer;
template <typename U>
struct rebind { typedef pool_allocator<U> other; };
pool_allocator() {}
~pool_allocator() {}
};



template <typename T> pool pool_allocator<T>::mem_;

template <typename T, typename U>
inline bool operator==(const pool_allocator<T>&, const
pool_allocator<U>){return true;}

template <typename T, typename U>
inline bool operator!=(const pool_allocator<T>&, const
pool_allocator<U>){return false;}



int main()
{
m[2] = 3.0;
}


John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top