Help with STL allocators

Discussion in 'C++' started by mar00ned, Sep 24, 2004.

  1. mar00ned

    mar00ned Guest

    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
     
    mar00ned, Sep 24, 2004
    #1
    1. Advertising

  2. "mar00ned" <> wrote in message
    news:...
    > 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
     
    John Harrison, Sep 24, 2004
    #2
    1. Advertising

  3. mar00ned

    Rohit Mattoo Guest

    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





    "John Harrison" <> wrote in message
    news:...
    >
    > "mar00ned" <> wrote in message
    > news:...
    > > 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
    >
    >
     
    Rohit Mattoo, Sep 24, 2004
    #3
  4. "Rohit Mattoo" <> wrote in message
    news:...
    > 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
     
    John Harrison, Sep 24, 2004
    #4
  5. mar00ned

    Rohit Mattoo Guest

    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






    "John Harrison" <> wrote in message
    news:...
    >
    > "Rohit Mattoo" <> wrote in message
    > news:...
    > > 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
    >
    >
     
    Rohit Mattoo, Sep 24, 2004
    #5
  6. mar00ned

    Tom Widmer Guest

    On Fri, 24 Sep 2004 14:06:41 +0100, "Rohit Mattoo" <>
    wrote:

    >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
     
    Tom Widmer, Sep 24, 2004
    #6
  7. "Rohit Mattoo" <> wrote in message
    news:...
    > 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;}

    std::map<int, float, std::less<int>, pool_allocator<std::pair<int, float> >
    > m;



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


    John
     
    John Harrison, Sep 24, 2004
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ross Ridge
    Replies:
    2
    Views:
    892
    Dhruv
    Jul 7, 2003
  2. Richard Smith
    Replies:
    20
    Views:
    1,007
    Andy Sawyer
    Jul 21, 2003
  3. Mark A. Gibbs

    operator= in allocators

    Mark A. Gibbs, Apr 4, 2004, in forum: C++
    Replies:
    9
    Views:
    431
    Mark A. Gibbs
    Apr 4, 2004
  4. Ares Lagae

    Containers & Allocators

    Ares Lagae, Feb 15, 2005, in forum: C++
    Replies:
    6
    Views:
    407
    Ares Lagae
    Feb 21, 2005
  5. sheam
    Replies:
    7
    Views:
    368
    Frank Birbacher
    Jun 12, 2008
Loading...

Share This Page