This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: _ExtPtr_allocator


On 21 June 2011 04:25, Bob Walters wrote:
> Jonathan,
> Sorry for this very delayed response.

Hi Bob,
no problem, I've been on holiday anyway.

> On Fri, Jun 10, 2011 at 5:06 PM, Jonathan Wakely <jwakely.gcc@gmail.com> wrote:
>> Does code using this allocator actually pass the 'pointer' type to
>> construct() and destroy()?
>
> Yes. ?When a container supports non-standard pointer types, it would
> infer the internal pointer types from Alloc<T>::pointer, and
> associated rebinds. ?Thus it would expect to be able to pass
> Alloc<T>::pointer to the allocator.

That's what I thought too, but as I did more work on adapting the
containers to use the new allocator model I realised it's not
sufficient.

In C++0x all container elements are constructed/destroyed via
std::allocator_traits<Alloc>::construct/destroy, and those functions
doesn't take the allocator's custom pointer type.  The choices there
are to specialize allocator_traits for every allocator with a custom
pointer type (which adds to the work that authors of such allocators
must do, defeating one of the purposes of allocator_traits which is to
remove the need for boiler plate code in custom allocators) or for the
code using the allocator to obtain a raw pointer via
std::addressof(*p)

typedef allocator_traits<Alloc> tr;
auto p = tr::allocate(a, 1);
tr::construct(a, std::addressof(*p), x);

This is what my work-in-progress does now.

I think it is still useful for the extptr allocator to also have the
overloaded members taking the custom pointer type, so it can be used
more easily in user code that doesn't need or want to make indirect
calls via allocator_traits, but the std containers can't rely on the
extra construct/destroy overloads, so need to dereference and get a
real pointer.

>> If my change breaks the allocator I see two simple fixes:
>>
>> * overload construct and destroy so both the old- and new-style
>> signatures are present.
>>
>> ? ? ?template<typename... _Args>
>> ? ? ? ?void
>> ? ? ? ?construct(pointer __p, _Args&&... __args)
>> ? ? ? ?{ construct(__p.get(), std::forward<_Args>(__args)...); }
>>
>> ? ? ?void destroy(pointer __p)
>> ? ? ?{ destroy(__p.get()); }
>>
>> I'd appreciate some advice from people familiar with this code as I
>> don't know it well enough or have time to study it properly right now.
>
> I wonder if the following might help: ?The __Pointer_Adapter has
> associated code and macros in ext/cast.h which are meant to allow code
> to be written without concern for whether the pointer typedef is a
> standard pointer or some class. ?This would allow methods like:
>
> template<typename _Uptr, typename... _Args>
> void
> construct( _Uptr __p, _Args&&... __args) {
> ?::new( __gnu_cxx::__static_pointer_cast<void*>(__p)) ?typename
> pointer_traits<_Uptr>::element_type( forward<Args>(args)... );
> }
>
> That works (I think) for _Uptr being a standard or non-standard
> pointer type, so long as any pointer class provides a working override
> for the ext/cast.h functions, which was proposed as one of the
> 'requirements' of any non-standard pointer that is used with libstdc++
> containers. ?i.e. The cast functions provided a way for the containers
> to be written without concern for pointer types. ?The convention was
> that the container just had to use the pointer typedef for storage and
> the __pointer_cast methods in place of standard casts. ?This avoids
> that __p.get() in the code, and the need for overrides.

That would work, but C++0x has taken a different approach, using
std::pointer_traits and std::allocator_traits, so I want the
containers to support non-standard pointers without any additional
non-standard specializations.  A static_pointer_cast was suggested and
rejected for this round of standardization (see
http://lwg.github.com/issues/lwg-closed.html#1289 for details), so I
don't want to rely on it or require users to overload it for their
pointer types.

I think it would be good if the ExtPtr_allocator could continue to
serve as an example of how to write a custom allocator in both C++03
and C++11, so I'll try not to break it!

Thanks very much for the feedback.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]