Why we need a "rebind" struct in allocator?

A

asm23

Hi, I found many tutorials that talk about this issue. All they say it
it just create another type allocator from the original type allocator.
For example:

//myallocator
template<class _Ty>
class myallocator
{
public:

template<class _Other>
struct rebind
{
typedef myallocator<_Other> other;
};
//...
}




typedef myallocator<int> mi;
typedef mi::rebind<double>::eek:ther md; // *1*
typedef myallocator<double> md; // *2*

So, you can see, the above two statement just has the same meaning.
My question is: Why we need a rebind member. It seems that *2* can do
the same thing.

Thank you very much.
 
L

Leandro Melo

Hi, I found many tutorials that talk about this issue. All they say it
it just create another type allocator from the original type allocator.
For example:

//myallocator
   template<class   _Ty>
   class   myallocator
   {
   public:

       template<class   _Other>
       struct   rebind
       {
           typedef   myallocator<_Other>   other;
        };
    //...
   }

   typedef   myallocator<int>   mi;
   typedef   mi::rebind<double>::eek:ther   md;     //   *1*
   typedef   myallocator<double>   md;           //   *2*

So, you can see, the above two statement just has the same meaning.
My question is: Why we need a rebind member. It seems that *2* can do
the same thing.

Thank you very much.


In your example you assume that one has access to the class template
myallocator so it's possible to parameterize it and define another
type. However, if you take a look at STL containers you'll notice that
their declaration is usually similar to this:

//Just an example.
template <class T, class Alloc = allocator<T> >
class vector
{
//...
};

As you can see, an allocator *type* is supposed to be passed as a
template argument. Not an allocator class template. So, if you need an
allocator for a different type from inside vector, your only choice is
to use the rebind member. Got the difference?

You might now wonder why allocators are not parameterized as template
template arguments so this could be avoided. I'm not sure about the
answer. Perhaps because it wouldn't be possible to know the template
parameters of every possible allocator, unless this was made clear in
the Standard (for example, using concepts like in the new C++0x). Or
maybe because template template arguments were not available by the
time the STL was originally designed. Can anyone give more details?
 
A

asm23

Leandro said:
In your example you assume that one has access to the class template
myallocator so it's possible to parameterize it and define another
type. However, if you take a look at STL containers you'll notice that
their declaration is usually similar to this:

//Just an example.
template <class T, class Alloc = allocator<T> >
class vector
{
//...
};

As you can see, an allocator *type* is supposed to be passed as a
template argument. Not an allocator class template. So, if you need an
allocator for a different type from inside vector, your only choice is
to use the rebind member. Got the difference?
Thank you for your declaration.
I have thinking this for several hours. This the code I copied from the
std list source code.

typedef typename _Alloc::template rebind<_List_node<_Tp> >::eek:ther
_Node_alloc_type;

typedef typename _Alloc::template rebind<_Tp>::eek:ther _Tp_alloc_type;


As a node of list, it should add two pointers to reference the previous
and next node, so, it seems that another allocator

rebind<_List_node<_Tp> > will be created.

But, sorry, it is still some confusing to understand.
 
J

Juha Nieminen

asm23 said:
But, sorry, it is still some confusing to understand.

When you create a std::list<int>, std::list will *not* allocate
objects of type int. Instead, it will have something like this inside
its private part:

struct Node
{
T elementType; // In this case T is int
Node *next, *prev;
};

Now std::list has to allocate objects of type Node, not of type int.
It has been provided with an allocator<int>, so how could it ever be
able to use that allocator to allocate objects of type Node instead?
It would need an allocator of type allocator<Node>, but it has been
given one of type allocator<int>.

The user having to give it an allocator of type allocator<Node> would
be a really horrible solution at all possible levels. Node would have to
be a public type, the user would have to know it exists, doing this
exposes the inner workings of std::list, and whatnot.

The answer is the rebind functionality of allocators. It can be used
by std::list to get an allocator of type allocator<Node> *from* the
given allocator (in this case allocator<int>). If the given allocator
had some special attributes, these will be copied to the new allocator.
All this behind the scenes, without the user having to bother.
 
A

asm23

Juha said:
When you create a std::list<int>, std::list will *not* allocate
objects of type int. Instead, it will have something like this inside
its private part:

struct Node
{
T elementType; // In this case T is int
Node *next, *prev;
};

Now std::list has to allocate objects of type Node, not of type int.
It has been provided with an allocator<int>, so how could it ever be
able to use that allocator to allocate objects of type Node instead?
It would need an allocator of type allocator<Node>, but it has been
given one of type allocator<int>.

The user having to give it an allocator of type allocator<Node> would
be a really horrible solution at all possible levels. Node would have to
be a public type, the user would have to know it exists, doing this
exposes the inner workings of std::list, and whatnot.

The answer is the rebind functionality of allocators. It can be used
by std::list to get an allocator of type allocator<Node> *from* the
given allocator (in this case allocator<int>). If the given allocator
had some special attributes, these will be copied to the new allocator.
All this behind the scenes, without the user having to bother.
Thank you for the informative explanation. I almost understand this idea.

By the way. I know the that the std::vector and std::list actually use
different type of allocate objects.

In std::vector, it use allocator<int>
In std::list, it use allocator<Node>.

For example, the code below:

template <class T> class malloc_allocator

{

public:

template <class U>

malloc_allocator(const malloc_allocator<U>&) {}

template <class U>

struct rebind { typedef malloc_allocator<U> other; };

...

};

Does it means that in std::vector, U==T? Since the malloc_allocator's
constructor should be a template function of both U and T. Does it means
T will directly pass to U?

Thank you.
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top