C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Container allocator - why not 'template template' parameter?

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Falk Tannhäuser
Guest





PostPosted: Thu Nov 18, 2004 12:25 pm    Post subject: Container allocator - why not 'template template' parameter? Reply with quote



[ This posting would perhaps better fit to comp.std.c++
but I have been unable to post there for the last few
days - I didn't even receive the usual confirmation email.
Did anybody else encounter similar troubles? ]

All standard container class templates have a type parameter
specifying the container's allocator, with a default argument
value being equal to 'std::allocator<value_type>'.
However, when instantiating the container template, there is
often the need to instantiate the allocator with another,
implementation defined type depending on value_type (for
example, in Cygwin g++ 3.4.1 implementation, std::deque
instantiates its allocator template not only with value_type,
but also with value_type*; std::list instantiates it with
std::_List_node<value_type> and the associative containers
with std::_Rb_tree_node<value_type>). Instantiating the
allocator class passed as template type parameter on another
value_type then the one that was specified by the user of the
container class template is achieved through a clever hack:

Each allocator class must be templatizated (?), and it must
contain a the following struct template member (§ 20.1.5/3):
template <class U> struct rebind { typedef allocator<U> other; };

This allows for example, when instantiating
std::list<double, MyAllocator MyList; // ***
to instantiate the class template MyAllocator<> on
std::_List_node<double> (or whatever the implementation uses
internally to store list nodes), while the instantiation
on double (although suggested by line ****) is never actually
needed for anything else than the rebinding (i.e. no calls
to MyAllocator<double>::allocate() will ever occur).

Now my question:
Wouldn't it have been nicer / simpler / more straightforward /
less misleading to make the allocator a template template
parameter of the containers (so that line *** would be rewritten
std::list<double, MyAllocator> MyList;
MyAllocator being a suitable class template as it has to be now,
just without the need for the "rebind hack")?
What is the rationale the Standard is the way it is now -
is it only historical (maybe containers with customisable
allocators appeared before and independently from template
template parameters in the drafting / standardisation process,
so the "rebind hack" was a means to circumvent the lack of
template template parameters) or is there some deeper reason
that I am missing?
I understand it is to late to change this now without breaking
tons of existing code, I'm just curious...

Falk

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Jonathan Turkanis
Guest





PostPosted: Fri Nov 19, 2004 3:27 pm    Post subject: Re: Container allocator - why not 'template template' parame Reply with quote




"Falk Tannhäuser" <clcppm-poster (AT) this (DOT) is.invalid> wrote

Quote:
[ This posting would perhaps better fit to comp.std.c++
but I have been unable to post there for the last few
days - I didn't even receive the usual confirmation email.
Did anybody else encounter similar troubles? ]

All standard container class templates have a type parameter
specifying the container's allocator, with a default argument
value being equal to 'std::allocator<value_type>'.
However, when instantiating the container template, there is
often the need to instantiate the allocator with another,
implementation defined type depending on value_type (for
example, in Cygwin g++ 3.4.1 implementation, std::deque
instantiates its allocator template not only with value_type,
but also with value_type*; std::list instantiates it with
std::_List_node<value_type> and the associative containers
with std::_Rb_tree_node<value_type>). Instantiating the
allocator class passed as template type parameter on another
value_type then the one that was specified by the user of the
container class template is achieved through a clever hack:

'rebind' is always called a hack, but to me it seems to be at least a trick, if
not a method or a paradigm.

Quote:
Each allocator class must be templatizated (?), and it must
contain a the following struct template member (§ 20.1.5/3):
template <class U> struct rebind { typedef allocator<U> other; };

This is not correct. The standard allocators are templates, but the requirement
(from Table 32) that an allocator have a nested rebind template does not imply
that the allocator itself must be a template. The requirement is simply that

typename X::template rebind<U>::other

be well-formed, where X is the allocator type and U is a type to be allocated.

Quote:
Now my question:
Wouldn't it have been nicer / simpler / more straightforward /
less misleading to make the allocator a template template
parameter of the containers (so that line *** would be rewritten
std::list<double, MyAllocator> MyList;
MyAllocator being a suitable class template as it has to be now,
just without the need for the "rebind hack")?

At the time the standard was approved, many compilers in wide use would not have
been able to handle template template parameters.

More importantly, it would have imposed an unnecessary restriction on
user-defined allocators. What if I want to define an allocator with three
template parameters -- one for the type to be allocated, and two policy
parameters? I can do this with the current framework:

template<typename T, typename P1, typename P2>
struct policy_allocator {
template<typename U>
struct rebind {
typedef policy_allocator<U, P1, P2> other;
};
...
};

vector< char, policy_allocator v;

If standard containers declared their allocator parameters as unary template
template parameters, I woldn't be able to use specializations of
policy_allocator with standard containers. I'd have to write something like
this:

template<typename P1, typename P2>
struct policy_allocator {
template<typename T>
struct alloc {
...
};
};

vector< char, policy_allocator v;

Quote:
Falk

Jonathan



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Bob Bell
Guest





PostPosted: Fri Nov 19, 2004 3:35 pm    Post subject: Re: Container allocator - why not 'template template' parame Reply with quote



Falk Tannhäuser <clcppm-poster (AT) this (DOT) is.invalid> wrote

Quote:
[ This posting would perhaps better fit to comp.std.c++
but I have been unable to post there for the last few
days - I didn't even receive the usual confirmation email.
Did anybody else encounter similar troubles? ]

I haven't tried to post there for a while, so I don't know.

[snip]

Quote:
Now my question:
Wouldn't it have been nicer / simpler / more straightforward /
less misleading to make the allocator a template template
parameter of the containers (so that line *** would be rewritten
std::list<double, MyAllocator> MyList;
MyAllocator being a suitable class template as it has to be now,
just without the need for the "rebind hack")?
What is the rationale the Standard is the way it is now -
is it only historical (maybe containers with customisable
allocators appeared before and independently from template
template parameters in the drafting / standardisation process,
so the "rebind hack" was a means to circumvent the lack of
template template parameters) or is there some deeper reason
that I am missing?
I understand it is to late to change this now without breaking
tons of existing code, I'm just curious...

My understanding is that it's historical, but the allocator doesn't
need to be a template:

class DoubleAllocator {
// necessary stuff to make this an allocator of doubles
};

std::list<double, DoubleAllocator> l;

Admittedly, DoubleAllocator is less reusable; personally I prefer the
template-template approach myself.

As for making this change in the standard library, I understood that
new stuff was going to be in a new namespace, so a new version of the
standard containers using template-template allocators could be placed
there. I have no idea if this is going to happen though.

Bob

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
George van den Driessche
Guest





PostPosted: Fri Nov 19, 2004 4:07 pm    Post subject: Re: Container allocator - why not 'template template' parame Reply with quote

"Falk Tannhäuser" <clcppm-poster (AT) this (DOT) is.invalid> wrote

[snip]
Quote:
Each allocator class must be templatizated (?), and it must
contain a the following struct template member (§ 20.1.5/3):
template <class U> struct rebind { typedef allocator<U> other; };
[snip]
Now my question:
Wouldn't it have been nicer / simpler / more straightforward /
less misleading to make the allocator a template template
parameter of the containers (so that line *** would be rewritten
std::list<double, MyAllocator> MyList;
MyAllocator being a suitable class template as it has to be now,
just without the need for the "rebind hack")?
What is the rationale the Standard is the way it is now -
is it only historical
[snip]


Yes, it's just historical, in the same way that 'this' is a pointer and not
a reference. In fact, it's not even very historical - where I am, the
compiler in use doesn't support template template parameters, and it's not
*that* old.

George



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Maxim Yegorushkin
Guest





PostPosted: Fri Nov 19, 2004 4:58 pm    Post subject: Re: Container allocator - why not 'template template' parame Reply with quote

On 18 Nov 2004 07:25:57 -0500, Falk Tannhäuser
<clcppm-poster (AT) this (DOT) is.invalid> wrote:

Quote:
Wouldn't it have been nicer / simpler / more straightforward /
less misleading to make the allocator a template template
parameter of the containers (so that line *** would be rewritten
std::list<double, MyAllocator> MyList;
MyAllocator being a suitable class template as it has to be now,
just without the need for the "rebind hack")?
What is the rationale the Standard is the way it is now -
is it only historical (maybe containers with customisable
allocators appeared before and independently from template
template parameters in the drafting / standardisation process,
so the "rebind hack" was a means to circumvent the lack of
template template parameters) or is there some deeper reason
that I am missing?

May be because that would put an unnecessary constraint that the allocator
type had to be a template with exactly one template parameter. The "rebind
hack" allows for greater flexibility with less troubles. For example, had
the allocators be used as template template parameters, emulating the
following would require some tricks:

template<class T, class U> struct my_alloc
{
template<class V> struct rebind { typedef my_alloc<V, U> other; };
// ...
};

typedef std::list<int, my_alloc L;

IMO, template template parameter are completely useless in the presence of
"rebind hack" technique. It's also interesting, that boost::mpl library
adhere to the latter technique and you might want to read mpl paper for
the rationale http://www.boost.org/libs/mpl/doc/paper/mpl_paper.html.

<q>
C++ templates are polymorphic with respect to their type arguments, but
not with respect to template template parameters. The arity (number of
parameters) of any template template parameter is strictly enforced, so we
still can't embed derive3 in a cons list. Moreover, polymorphism between
types and metafunctions is not supported (the compiler expects one or the
other), and as we've seen, the syntax and semantics of “returned�
metafunctions is different from that of returned types. Trying to
accomplish everything with the simple template metafunction form would
seriously limit the applicability of higher-order metafunctions and would
have an overall negative effect on the both conceptual and implementation
clarity, simplicity and size of the library.
</q>

--
Maxim Yegorushkin

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Jonathan Turkanis
Guest





PostPosted: Sat Nov 20, 2004 10:25 am    Post subject: Re: Container allocator - why not 'template template' parame Reply with quote


"Maxim Yegorushkin" <e-maxim (AT) yandex (DOT) ru> wrote:

Quote:
IMO, template template parameter are completely useless in the presence of
"rebind hack" technique. It's also interesting, that boost::mpl library
adhere to the latter technique and you might want to read mpl paper for
the rationale http://www.boost.org/libs/mpl/doc/paper/mpl_paper.html.

I agree that template template parameters need never (and perhaps should never)
be exposed to library users. But they are often needed by library writers. For
instance, I believe MPL needs template template parameters in order to parse
lambda expressions involving user-defined metafunctions (unless they use the
lambda support macros).

I mention several other uses here:

http://lists.boost.org/MailArchives/boost/msg74171.php

Best Regards,
Jonathan



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.