mirror of
https://github.com/reactos/reactos.git
synced 2024-11-07 15:10:53 +00:00
90 lines
3.6 KiB
Text
90 lines
3.6 KiB
Text
********************************************************************
|
|
* This document describe the STLport container pointer *
|
|
* specialization feature. *
|
|
********************************************************************
|
|
|
|
What is it for:
|
|
|
|
The major problem of template code is the potentialy huge binary
|
|
size that can result from the compilation. Each template type
|
|
instanciation is a new type from the compiler point of view even if
|
|
the generated binaries are identicals. To avoid this binary duplication
|
|
STLport grant the partial pointer specialization for 4 containers:
|
|
- vector
|
|
- deque
|
|
- list
|
|
- slist
|
|
|
|
How does it work:
|
|
|
|
The pointer specialization consists in using a void* container
|
|
instanciation for any container of pointers, including pointers
|
|
to cv qualified types. So the container pointer specializations
|
|
are only bridges that forward all the method calls to the
|
|
underlying void* container instanciation. The bridge job is to
|
|
cast the pointer type to and from the void* type.
|
|
|
|
Why only those 4 containers:
|
|
|
|
Some of you might wonder why none of the associative containers
|
|
or hash containers has been specialized. Lets take the set container
|
|
as an example. Its declaration is
|
|
|
|
template <class _Tp,
|
|
class _Compare = less<_Tp>,
|
|
class _Alloc = allocator<_Tp> >
|
|
class set;
|
|
|
|
In a first thought you can imagine a partial specialization like
|
|
the following:
|
|
|
|
template <class _Tp, class _Compare, class _Alloc>
|
|
class set<_Tp*, _Compare, _Alloc>
|
|
|
|
What would be the underlying container for such a partial
|
|
specialization? The _Alloc type is supposed to have a rebind member
|
|
method so you can easily find the _VoidAlloc type. The _Compare type,
|
|
on the other hand, do not have this kind of Standard requirements.
|
|
So you need to wrap the _Compare type within a _WrapCompare type
|
|
that will take care of all the cast work. The underlying container
|
|
type will be:
|
|
|
|
set<void*, _WrapCompare<_Tp, _Compare>, _VoidAlloc>
|
|
|
|
The problem of such a type is that it is still dependent on the
|
|
original _Tp type for the _WrapCompare instanciation. So each set
|
|
instanciation will have a distinct underlying void* container and
|
|
we fall back on a binary duplication trouble.
|
|
|
|
On a second thought a possible solution is to limit the partial
|
|
specialization like that:
|
|
|
|
template <class _Tp, class _Alloc>
|
|
class set<_Tp*, less<_Tp*>, _Alloc>
|
|
|
|
We only specialized the set container if the comparison functor
|
|
is the Standard less struct. The underlying container would be:
|
|
|
|
set<void*, less<void*>, _VoidAlloc>
|
|
|
|
It looks fine but it is wrong. Actually a STL user is free to
|
|
specialized the less struct for any pointer type even the basic one.
|
|
In such a situation the client would think that the set is ordered
|
|
according its own functor but will finally have a set ordered according
|
|
the less<void*> functor. The less specialization issue also show that
|
|
the underlying cannot be a
|
|
|
|
set<void*, less<void*>, _VoidAlloc>
|
|
|
|
but will have to be a
|
|
|
|
set<void*, __less<void*>, _VoidAlloc>
|
|
|
|
where __less would be equivalent to the standard less functor but
|
|
would not be specializable because unreachable from the client code.
|
|
|
|
There is of course a solution for this specialization issue. We
|
|
need to be able to detect the less specialization. The partial set
|
|
specialization would have to be used only if the less functor is
|
|
the default STLport implementation based on the strict ordering operator.
|
|
No doubt that a solution to this problem will be soon found.
|